home *** CD-ROM | disk | FTP | other *** search
/ PC Format Collection 21 / PC Format CD-ROM Collection 21 (1995-12)(Future Publishing)(GB)[issue 51].iso / resource / show'em.poc < prev    next >
Text File  |  1992-10-15  |  78KB  |  3,334 lines

  1. // Show'em.poc - A program which makes fancy bulleted text slide presentations
  2. // out of simple text files.    This POCO routine can be used with Autodesk's
  3. // Animator Pro Version 1.3 or higher.
  4. //
  5. // Copyright 1992 Michael Edmonds and Dancing Flame
  6. // This file may be copied, used, and modified by legal license holders of
  7. // the Autodesk Animator Pro.
  8.  
  9.  
  10. // Need to make sure we're running the right version of Animator Pro.
  11. #if __POCO__ < 181
  12.     #error "You must upgrade to Animator Pro 1.3 or later to run this program"
  13. #endif
  14.  
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <optics.h>
  18.  
  19. //-------------------------------------------------------------------------
  20. //     Defines and stuff you know and love
  21. //-------------------------------------------------------------------------
  22. #define TRUE 1
  23. #define FALSE 0
  24. #define Success 0
  25. #define EOS 0
  26. #define ESCAPE_KEY 0x1b
  27. #define PIXEL_SIZE 1
  28.     /* Flags for disabling buttons on a QmenuWithFlags() */
  29. #define QMF_DISABLED (1<<0)
  30. #define QMF_ASTERISK (1<<1)
  31. static char *off_on[2] = {"OFF", "ON"};
  32.  
  33.  
  34. /* A little macro that prints out the line number.  Useful for debugging. */
  35. #define TBOX Qtext("%s %d", __FILE__,__LINE__ );
  36.  
  37. typedef struct 
  38. /* A color.  R(ed), G(reen), B(lue) go from 0 to 255 */
  39.     {
  40.     int r,g,b;
  41.     } RGB;
  42.  
  43. typedef struct
  44. /* Two dimensional point. */
  45.     {
  46.     int x,y;
  47.     } XY;
  48.  
  49. //-------------------------------------------------------------------------
  50. //             Persistant Variables
  51. //   (ones which persist between runs of program.)
  52. //-------------------------------------------------------------------------
  53. #define UNTITLED_TEXT "untitled.txt"
  54. Boolean text_changed = FALSE;
  55. Boolean text_named = FALSE;
  56. char text_file_name[PATH_SIZE] = UNTITLED_TEXT;
  57.  
  58. static char pn_text_changed[] = "show'em.text_changed";
  59. static char pn_text_named[] = "show'em.text_named";
  60. static char pn_text_file_name[] = "show'em.text_file_name";
  61.  
  62. Boolean get_persistant_boolean(char *var_name, Boolean default_val)
  63. /*
  64.  * This will return the TRUE if the value of var_name is "TRUE",  else
  65.  * FALSE.  If the var_name does not exist returns default_val.
  66.  */
  67. {
  68. char buf[10];
  69. if (GlobalVarGet(var_name, buf) >= Success)
  70.     {
  71.     return (stricmp(buf, "TRUE") == 0);
  72.     }
  73. else
  74.     return default_val;
  75. }
  76.  
  77. Errcode save_persistant_boolean(char *var_name, Boolean val)
  78. {
  79. if (val)
  80.     return GlobalVarSet(var_name, "TRUE");
  81. else
  82.     return GlobalVarSet(var_name, "FALSE");
  83. }
  84.  
  85. void load_persistant()
  86. /*
  87.  * Load in all persistant variables.
  88.  */
  89. {
  90. text_changed = get_persistant_boolean(pn_text_changed, text_changed);
  91. text_named = get_persistant_boolean(pn_text_named, text_named);
  92. GlobalVarGet(pn_text_file_name, text_file_name);
  93. }
  94.  
  95. void save_persistant()
  96. {
  97. save_persistant_boolean(pn_text_changed, text_changed);
  98. save_persistant_boolean(pn_text_named, text_named);
  99. GlobalVarSet(pn_text_file_name, text_file_name);
  100. }
  101.  
  102. //-------------------------------------------------------------------------
  103. //             Global Variables
  104. //-------------------------------------------------------------------------
  105.  
  106. char persistant_text[] = "=:show'em.txt";
  107. char persistant_style[] = "=:show'em.sty";
  108. int slide_width, slide_height;
  109. int shadow_xoff, shadow_yoff;
  110. FILE *script;
  111.  
  112.  
  113. //-------------------------------------------------------------------------
  114. //             Menu Definitions
  115. //-------------------------------------------------------------------------
  116.  
  117. static char mm_header[] = "Show'em 1.0";
  118. static char *mm_choices[] = 
  119.     {
  120.     "Help",
  121.     "Create Slide Show",
  122.     "Set Slide Style",
  123.     "Exit",
  124.     };
  125. static enum { MAIN_EXIT, MAIN_HELP, MAIN_CREATE, MAIN_FORMAT};
  126.  
  127. static char mm_help1[] =
  128. "Show'em creates a slide presentation from simple text input. "
  129. "All slides in a presentation share a background, logo, title, and "
  130. "bullet style.  You can specify the fonts, colors, and styles with "
  131. "the Set Slide Style menu. Then, from the Create Slide Show menu, "
  132. "you define the text, preview the slides, and render them. "
  133.     ;
  134.  
  135. static char mm_help2[] =
  136. "Show'em creates a numbered series of pictures, animated images, "
  137. "Autodesk Animator Pro Player scripts, and a batch file to play the "
  138. "scripts.  To present a slide show in its final form, select "
  139. "Create Slide Show and then Render Slides. Then, exit Animator Pro "
  140. "and use the batch file created with Show'em to run it.  The batch file "
  141. "uses Aniplay and the scripts and images produced by Show'em to run "
  142. "your slide show. "
  143.      ;
  144.  
  145. static char *mm_help[] = {mm_help1, mm_help2};
  146.  
  147. static char css_header[] = "Create Slide Show";
  148. static char *css_choices[] =
  149.     {
  150.     "Help",
  151.     "Edit Text",
  152.     "Load Text",
  153.     "Save Text",
  154.     "New Text",
  155.     "Preview",
  156.     "Render Slides",
  157.     "Return",
  158.     };
  159. static enum {CSS_EXIT, CSS_HELP, CSS_EDIT, CSS_LOAD, CSS_SAVE, CSS_NEW
  160. , CSS_PREVIEW, CSS_RENDER};
  161.  
  162. static char *css_help[] = {
  163. "To create a slide show, you define the text for each slide.  You can "
  164. "load the slide text from an ascii text file or you can enter the text "
  165. "directly by selecting Edit Text. Each paragraph of text (separated "
  166. "by a blank line) creates one slide. The first line of each paragraph "
  167. "becomes the title.  Subsequent lines become bullet items."
  168. ,
  169. "There are also a few commands you can put in the text that allow "
  170. "you to (1) eliminate the pause between items in an animated slide; "
  171. "(2) include clips like business charts, AutoCAD slides, and scanned "
  172. "images right on your slides; (3) show any animation or picture within "
  173. "your presentation; and (4) place an interactive demo in the middle of "
  174. "your presentation and return to your presentation automatically. "
  175. ,
  176. "You can insert the following commands in your input text. "
  177. "They must be in lower case and on a line by themselves. "
  178. "\n\n"
  179. "\"-nopause\" Suppress the pause that Show'em puts between animated "
  180. "items on a slide. "
  181. "\n\n" 
  182. "\"-i ...\" Follow this by the file name of a cel you want pasted on a slide. "
  183. "\n\n" 
  184. "\"-x ...\" Follow this with any Animator Pro Player script "
  185. "command.  This must be in its own single line paragraph. "
  186. "\n\n" 
  187. "\"-b ...\" Follow this with any valid DOS command.  "
  188. "This must be in its own single line paragraph.  "
  189. };
  190.  
  191. static char ssf_header[] = "Set Slide Style";
  192. static char *ssf_choices[] =
  193.     {
  194.     "Help",
  195.     "Title",
  196.     "Items",
  197.     "Bullet",
  198.     "Background",
  199.     "Logo",
  200.     "Output",
  201.     "Load Style",
  202.     "Save Style",
  203.     "Return",
  204.     };
  205. static enum {SSF_EXIT, SSF_HELP, SSF_TITLE, SSF_ITEMS, SSF_BULLET
  206. , SSF_BACKGROUND, SSF_LOGO, SSF_OUTPUT, SSF_LOAD, SSF_SAVE};
  207. static char ssf_help[] =
  208. "This menu controls the slide style.\n"
  209. "\n" 
  210. "Title - Set the title color, font,\n"
  211. "   position, and justification.\n"
  212. "Items - Set the item color and font.\n"
  213. "Bullet - Set bullet color, use a circle\n"
  214. "   bullet, load a cel to use as the\n"
  215. "   bullet, or use no bullet.\n"
  216. "Background - Set the background color,\n"
  217. "   solid or gradient, or load an image\n"
  218. "   to use as background.\n"
  219. "Logo - Load a cel to use as logo,\n"
  220. "   position it, or don't use a logo.\n"
  221. "Output - Set slides as still images or\n"
  222. "   animated with scrolling or fading;\n"
  223. "   turn antialiasing on and off; turn\n"
  224. "   safe titling on and off; get help.\n"
  225. "Load Style - Load a style file.\n"
  226. "Save Style - Save a style file.\n"
  227.     ;
  228.  
  229. static char title_header[] = "Title Style";
  230. static char *title_choices[] =
  231.     {
  232.     "Title Color",
  233.     "Title Font",
  234.     "Position Title",
  235.     "Justify Title",
  236.     "Return",
  237.     };
  238. static enum {TITLE_EXIT, TITLE_COLOR, TITLE_FONT, TITLE_POS, TITLE_JUST};
  239. static char title_just_header[] = "Title Justification";
  240. static char *title_just_choices[] =
  241.     {
  242.     "Left",
  243.     "Right",
  244.     "Center",
  245.     "Fill",
  246.     "Return",
  247.     };
  248.  
  249. static char item_header[] = "Item Style";
  250. static char *item_choices[] =
  251.     {
  252.     "Item Color",
  253.     "Item Font",
  254.     "Return",
  255.     };
  256. static enum {ITEM_EXIT, ITEM_COLOR, ITEM_FONT};
  257.  
  258. static char bullet_header[] = "Set Bullet Image";
  259. static char *bullet_choices[] =
  260.     {
  261.     "Set Bullet Color",
  262.     "Use a Circle for Bullets",
  263.     "Load a Cel for Bullets",
  264.     "Don't Use Bullets",
  265.     "Return",
  266.     };
  267. static enum {BULLET_EXIT
  268. , BULLET_COLOR, BULLET_CIRCLE, BULLET_USE_CEL, BULLET_NONE};
  269.  
  270. static char background_header[] = "Set Background Image";
  271. static char *background_choices[] =
  272.     {
  273.     "Set Background Color",
  274.     "Use a Solid Background",
  275.     "Use a Gradient Background",
  276.     "Load Background Image",
  277.     "Return",
  278.     };
  279. static enum {BACKGROUND_EXIT, BACKGROUND_GET_COLOR
  280. , BACKGROUND_SOLID, BACKGROUND_GRADIENT, BACKGROUND_USE_PIC};
  281.  
  282. static char logo_header[] = "Logo Style";
  283. static char *logo_choices[] =
  284.     {
  285.     "Load a Logo Cel",
  286.     "Position Logo Cel",
  287.     "Don't Use a Logo",
  288.     "Return",
  289.     };
  290. static enum {LOGO_EXIT, LOGO_USE_CEL, LOGO_POSITION, LOGO_NONE};
  291.  
  292. static char out_header[] = "Set Output Style";
  293. static char *out_choices[] =
  294.     {
  295.     "Help",
  296.     "Still Images",
  297.     "Scrolling",
  298.     "Fading",
  299.     "Anti-aliasing",
  300.     "Safe Titling",
  301.     "Preview",
  302.     "Return",
  303.     };
  304. static enum {OUT_EXIT, OUT_HELP
  305. , OUT_STILL, OUT_SCROLL, OUT_FADE, OUT_ANTIALIAS, OUT_SAFE_TITLE, OUT_PREVIEW};
  306. static char out_help1[] =
  307. "The output menu contains these options:\n"
  308. "\n"
  309. "Still Images - The bullet items are not\n"
  310. "   animated.  Slides are written as \n"
  311. "   single frame flic files.\n"
  312. "Scrolling - The bullet items are\n"
  313. "   animated, scrolling onto the screen\n"
  314. "   from the right.  The slides are saved\n"
  315. "   in a combination of Flic files.\n"
  316. "Fading - The bullet items are animated,\n"
  317. "   fading onto the screen. The slides\n"
  318. "   are saved in a combination of Flic\n"
  319. "   files.\n"
  320. "Anti-aliasing - Toggles smoothing of\n"
  321. "   edges on and off. When on the images\n"
  322. "   render slower but look a bit better.\n"
  323. "Safe Titling - Toggles the reduction of\n"
  324. "   the slide size on the screen so your\n"
  325. "   titles are fully visible when shown\n"
  326. "   on a TV.\n"
  327.     ;
  328.  
  329.  
  330.  
  331. //-------------------------------------------------------------------------
  332. //     Some Utility Routines maybe we'll use in  another poco program too
  333. //-------------------------------------------------------------------------
  334.  
  335. Boolean ignore_changes()
  336. /*
  337.  *     If have made changes to flic make sure it's ok to ignore them.
  338.  */
  339. {
  340.     int changes;
  341.     static char replace_changes_prompt[]  
  342.     = "Okay to discard current flic?\n"
  343.     "(You have unsaved changes)";
  344.  
  345.     if ((changes = GetChangeCount()) != 0)
  346.         return Qquestion(replace_changes_prompt);
  347.     else
  348.         return TRUE;
  349. }
  350.  
  351. Boolean overwrite_ok(char *file_name)
  352. /*
  353.  *     If file exists make sure it's ok to overwrite it.
  354.  */
  355. {
  356.     if (DosExists(file_name))
  357.         return Qquestion("Write over old %s", file_name);
  358.     else
  359.         return TRUE;
  360. }
  361.  
  362. FILE *must_open(char *file_name, char *mode)
  363. /*
  364.  * Open file to read.  Complain if can't.
  365.  */
  366. {
  367.     FILE *f;
  368.     char c = tolower(mode[0]);
  369.  
  370.     if ((f = fopen(file_name, mode)) == NULL)
  371.         {
  372.         if (c == 'w')
  373.             Qtext("Can't create %s, sorry\n", file_name);
  374.         else
  375.             Qtext("Can't find %s, sorry\n", file_name);
  376.         }
  377.     return f;
  378. }
  379.  
  380. void *need_memory(unsigned size)
  381. /*
  382.  * Request memory.  Squawk if can't get it.
  383.  */
  384. {
  385.     void *pt;
  386.  
  387.     if ((pt = malloc(size)) == NULL)
  388.         Qtext("Couldn't find %d bytes of free memory, sorry", size);
  389.     return pt;
  390. }
  391.  
  392. Boolean copy_file(char *source, char *dest)
  393. /*
  394.  * Copy one file to another. 
  395.  */
  396. {
  397.     FILE *s, *d;
  398.     int c;
  399.     Boolean ok = FALSE;
  400.  
  401.     if ((s = must_open(source, "rb")) != NULL)
  402.         {
  403.         if ((d = must_open(dest, "wb")) != NULL)
  404.             {
  405.             while ((c = getc(s)) != EOF)
  406.                 {
  407.                 if (putc(c, d) == EOF)
  408.                     {
  409.                     Qtext("Couldn't copy %s to %s,  %s truncated"
  410.                     , source, dest, dest);
  411.                     break;
  412.                     }
  413.                 }
  414.             fclose(d);
  415.             }
  416.         fclose(s);
  417.         ok = TRUE;
  418.         }
  419.     return ok;
  420. }
  421.  
  422.  
  423. char *skip_space(char *pt)
  424. /*
  425.  * Return first non-space character in string, or NULL if all spaces
  426.  *  until end.
  427.  */
  428. {
  429.     if (pt == NULL)
  430.         return NULL;
  431.     while (isspace(*pt))
  432.         ++pt;
  433.     if (*pt == EOS)
  434.         return(NULL);
  435.     return(pt);
  436. }
  437.  
  438. char *skip_to_space(char *pt)
  439. /*
  440.  * Return first space character (or EOS) character in string. 
  441.  */
  442. {
  443.     char c;
  444.  
  445.     for (;;)
  446.         {
  447.         c = *pt;
  448.         if (isspace(c) || c == EOS)
  449.             break;
  450.         ++pt;
  451.         }
  452.     return(pt);
  453. }
  454.  
  455. void file_name_only(char *path, char *file_only)
  456. /*
  457.  * Extract just the file name from a path.    That is
  458.  *  convert C:\ANI\DUCKY.FLI  to    DUCKY.FLI
  459.  */
  460. {
  461. char dev[4], dir[70], file[10], suff[5];  /* FNsplit/merge stuff */
  462.  
  463. fnsplit(path,dev,dir,file,suff);
  464. sprintf(file_only, "%s%s", file, suff);
  465. }
  466.  
  467. void translate_to_rgb(int index, RGB *color)
  468. /*
  469.  * Look up color map index and store it in color
  470.  */
  471. {
  472.     GetColorMap(index, &color->r, &color->g, &color->b);
  473. }
  474.  
  475. void multi_screen_help(char *screens[], int screen_count)
  476. /*
  477.  * Put up multiple screens of help.  Pass in an array of strings, one
  478.  * for each string.  This will put up a series of dialogs, one for each
  479.  * screen,  and let the user navigate back and forth between them.
  480.  * Returns when user selects "done" or right clicks out.
  481.  */
  482. {
  483. static char prev_string[] = "Previous";
  484. static char next_string[] = "Next";
  485. static char done_string[] = "Done";
  486. static char *done[1] = {done_string};
  487. static char *done_next[2] = {done_string, next_string};
  488. static char *prev_done_next[3] = {prev_string, done_string, next_string};
  489. static char *prev_done[2] = {prev_string, done_string};
  490.  
  491. if (screen_count == 1)
  492.     Qchoice(done, Array_els(done), screens[0]);
  493. else
  494.     {
  495.     int screen_index = 0;
  496.     int choice;
  497.     for (;;)
  498.         {
  499.         if (screen_index == 0)
  500.             {
  501.             choice = Qchoice(done_next, Array_els(done_next)
  502.             , screens[screen_index]);
  503.             switch (choice)
  504.                 {
  505.                 case 2:
  506.                     ++screen_index;
  507.                     break;
  508.                 default:
  509.                     return;
  510.                 }
  511.             }
  512.         else if (screen_index == screen_count - 1)
  513.             {
  514.             choice = Qchoice(prev_done, Array_els(prev_done)
  515.             , screens[screen_index]);
  516.             switch (choice)
  517.                 {
  518.                 case 1:
  519.                     --screen_index;
  520.                     break;
  521.                 default:
  522.                     return;
  523.                 }
  524.             }
  525.         else
  526.             {
  527.             choice = Qchoice(prev_done_next, Array_els(prev_done_next)
  528.             , screens[screen_index]);
  529.             switch (choice)
  530.                 {
  531.                 case 1:
  532.                     --screen_index;
  533.                     break;
  534.                 case 3:
  535.                     ++screen_index;
  536.                     break;
  537.                 default:
  538.                     return;
  539.                 }
  540.             }
  541.         }
  542.     }
  543. }
  544.  
  545.  
  546. //-------------------------------------------------------------------------
  547. // Some font related stuff.
  548. //-------------------------------------------------------------------------
  549.  
  550. void full_font_name(char *name, char *path)
  551. /*
  552.  * This removes any existing directory info from name and replaces it
  553.  * with the current font directory.  The result is in path.
  554.  */
  555. {
  556. char name_only[PATH_SIZE];
  557.  
  558. GetFontDir(path);
  559. file_name_only(name, name_only);
  560. strcat(path, name_only);
  561. }
  562.  
  563. ErrCode load_font(char *name)
  564. /*
  565.  * Load font, looking if necessary in the font directory for it.
  566.  * Also keep last font name used for reference to prevent unnecessary
  567.  * reloading of font.
  568.  */
  569. {
  570. char fdir[80];
  571. ErrCode err;
  572. static char last_font_name[PATH_SIZE];
  573.  
  574.  
  575. if (strcmp(last_font_name, name) == 0)
  576.     return Success;
  577. if ((err = LoadFont(name)) < Success)
  578.     {
  579.     full_font_name(name, fdir);
  580.     err =  Qerror(LoadFont(fdir), "Loading font %s", fdir);
  581.     }
  582. strcpy(last_font_name, name);
  583. return err;
  584. }
  585.  
  586.  
  587. typedef struct
  588. /*
  589.  * Holds all pertinant info about type face - font size spacing data.
  590.  */
  591.     {
  592.     char name[PATH_SIZE];
  593.     int size, spacing, leading;
  594.     } Font_style;
  595.  
  596. void get_font_style(Font_style *fs)
  597. /*
  598.  * Get current status of font into Font_style
  599.  */
  600. {
  601.     GetFontName(fs->name);
  602.     fs->spacing = GetFontSpacing();
  603.     fs->leading = GetFontLeading();
  604.     fs->size = FontHeight() - fs->leading;
  605. }
  606.  
  607. Boolean set_font_style(Font_style *fs)
  608. /*
  609.  * Set font from Font_style
  610.  */
  611. {
  612.     if (load_font(fs->name) < Success)
  613.         return FALSE;
  614.     ScaleFont(fs->size);
  615.     SetFontSpacing(fs->spacing);
  616.     SetFontLeading(fs->leading);
  617.     return TRUE;
  618. }
  619.  
  620.  
  621. //-------------------------------------------------------------------------
  622. // Some stuff to read a file a line at a time and report errors.
  623. //-------------------------------------------------------------------------
  624. typedef struct 
  625. /* This structure keeps track of where we are in a file. */
  626.     {
  627.     FILE *f;
  628.     char *file_name;
  629.     char *line_buf;
  630.     int buf_size;
  631.     int current_line;
  632.     char x_call[256];
  633.     char bat_call[256];
  634.     } Line_file;
  635.  
  636. Boolean line_file_open(Line_file *f, char *file_name, char *buf, int buf_size)
  637. /*
  638.  * Open up a file and set up structure to read it one line at a time
  639.  */
  640. {
  641.     if ((f->f = must_open(file_name, "r")) == NULL)
  642.         return FALSE;
  643.     f->file_name = file_name;
  644.     f->line_buf = buf;
  645.     f->buf_size = buf_size;
  646.     f->current_line = 0;
  647.     strcpy(f->x_call, "none");
  648.     strcpy(f->bat_call, "none");
  649.     return TRUE;
  650. }
  651.  
  652. void line_file_close(Line_file *f)
  653. /*
  654.  * Close a line file.
  655.  */
  656. {
  657.     if (f->f != NULL)
  658.         {
  659.         fclose(f->f);
  660.         f->f = NULL;
  661.         }
  662. }
  663.  
  664.  
  665. Boolean read_line(Line_file *file)
  666. /* 
  667.  * Read a line from file.  Return FALSE at EOF.
  668.  */
  669. {
  670.     char *pt;
  671.  
  672.     pt = file->line_buf;
  673.     pt = fgets(pt, file->buf_size, file->f);
  674.     ++file->current_line;
  675.     return (pt != NULL);
  676. }
  677.  
  678. Boolean must_read_line(Line_file *file)
  679. /* 
  680.  * Read a line from file 
  681.  * complain if it's not there.
  682.  */
  683. {
  684.     if (!read_line(file))
  685.         {
  686.         Qtext("%s %d:  file too short\n"
  687.         ,  file->file_name, file->current_line);
  688.         return FALSE;
  689.         }
  690.     return TRUE;
  691. }
  692.  
  693. void expecting_got(Line_file *file, char *expecting, char *got)
  694. /*
  695.  * Print "expecting/got" error message
  696.  */
  697. {
  698.     if (got == NULL)
  699.         got = "(NULL)";
  700.     if (skip_space(got) == NULL)
  701.         got = "<cr>";
  702.     Qtext("%s line %d:\nExpecting %s got %s"
  703.     , file->file_name, file->current_line
  704.     , expecting, got);
  705. }
  706.  
  707.  
  708. Boolean next_string(Line_file *file, char **input,  char *result, int max_size)
  709. /*
  710.  * Get next space separated token from input (and advance input).
  711.  */
  712. {
  713.     char *start;
  714.     char *end;
  715.     int size;
  716.  
  717.     if ((start = skip_space(*input)) == NULL)
  718.         return FALSE;
  719.     end = skip_to_space(start);
  720.     size = end - start;
  721.     if (size >= max_size)
  722.         {
  723.         Qtext("%s %d:\nToken \"%s\" too long.\nCan only handle %d characters\n"
  724.         ,  file->file_name, file->current_line, start, max_size-1);
  725.         *input = NULL;
  726.         return FALSE;
  727.         }
  728.     strncpy(result, start, size);
  729.     result[size] = EOS;
  730.     *input = end;
  731.     return TRUE;
  732. }
  733.  
  734. Boolean next_number(Line_file *file, char **input, int *result)
  735. /*
  736.  * Get next number from string.  
  737.  *  Put numerical result in *result.  Complain if it's not a number.
  738.  */
  739. {
  740.     char num_buf[64]; /* Long enough for any reasonable integer! */
  741.  
  742.     if (!next_string(file, input, num_buf, sizeof(num_buf)))
  743.         {
  744.         expecting_got(file, "number", "<cr>");
  745.         return FALSE;
  746.         }
  747.     if (!isdigit(num_buf[0]))
  748.         {
  749.         expecting_got(file, "number", num_buf);
  750.         return FALSE;
  751.         }
  752.     *result = atoi(num_buf);
  753.     return TRUE;
  754. }
  755.  
  756.  
  757. //-------------------------------------------------------------------------
  758. //     Style data structure.
  759. //-------------------------------------------------------------------------
  760.     /* Give names to various text justify modes. */
  761. enum Justify {JUST_LEFT, JUST_RIGHT, JUST_CENTER, JUST_FILL};
  762.     /* Give names to various animation modes. */
  763. enum AnimMode {AM_STILL, AM_SCROLL, AM_FADE};
  764.  
  765.  
  766. typedef struct 
  767. /* This guy holds our slide style. */
  768.     {
  769.     RGB background_color;
  770.     char background_image[PATH_SIZE];
  771.     RGB title_color;
  772.     Font_style title_font;
  773.     enum Justify title_justification;
  774.     XY title_position;
  775.     RGB item_color;
  776.     Font_style item_font;
  777.     char bullet_image[PATH_SIZE];
  778.     RGB bullet_color;
  779.     char logo_image[PATH_SIZE];
  780.     XY logo_position;
  781.     int antialias;
  782.     int safe_title;
  783.     enum AnimMode animode;
  784.     int aniframes;
  785.     int anispeed;
  786.     } Slide_style;
  787.  
  788. Slide_style default_style =
  789.     {
  790.     {100, 40, 255},                    /* Background Color. */
  791.     "gradient",                         /* Background Name */
  792.     {204, 108, 12,},                  /* Title Color */
  793.     {"SERB10.FNT", 67, 0, 0},      /* Title font, size, spacing, leading */
  794.     JUST_LEFT,                          /* Title justify */
  795.     {0,0,},                              /* Title position */
  796.     {60, 156, 156,},                  /* Item color */
  797.     {"SERB08.FNT", 48, 0, 0},      /* Item font, size, spacing, leading */
  798.     "circle",                            /* Bullet name */
  799.     {60, 156, 156,},                  /* Bullet color */
  800.     "none",                              /* Logo name */
  801.     {590, 50},                          /* Logo position */
  802.     FALSE,                                /* Antialias toggle*/
  803.     FALSE,                                /* Safe Title toggle
  804.     AM_STILL,                            /* Anim_mode */
  805.     0,                                     /* Anim frames */
  806.     0,                                     /* Anim speed (milliseconds) */
  807.     };
  808.  
  809. void set_default_style(Slide_style *sf)
  810. /* 
  811.  * Set style to default. 
  812.  */
  813. {
  814.     memcpy(sf, &default_style, sizeof(*sf));    /* Do most of the work here. */
  815.     full_font_name("SERB10.FNT", sf->title_font.name);
  816.     full_font_name("SERB08.FNT", sf->item_font.name);
  817. }
  818.  
  819. int get_title_width(Slide_style *sf)
  820. /*
  821.  * Figure out how wide to make title.
  822.  */
  823. {
  824. int sw,sh;
  825. GetSize(&sw, &sh);
  826. return sw - sf->title_position.x;
  827. }
  828.  
  829. //-------------------------------------------------------------------------
  830. //     Style File Save Routines
  831. //-------------------------------------------------------------------------
  832.  
  833. static char slide_style_magic[] = "Show'em 1.0 Slide Style:\n";
  834.  
  835. static Boolean write_rgb(FILE *f, RGB *rgb, char *label)
  836. /*
  837.  * Write out RGB triples and label to file.
  838.  */
  839. {
  840.     return (fprintf(f, "%d %d %d %s\n", rgb->r, rgb->g, rgb->b, label) > 0);
  841. }
  842.  
  843. static Boolean write_xy(FILE *f, XY *xy, char *label)
  844. /*
  845.  * Write out XY pair and label to file.
  846.  */
  847. {
  848.     return (fprintf(f, "%d %d %s\n", xy->x, xy->y, label) > 0);
  849. }
  850.  
  851. static Boolean write_font_style(FILE *f, Font_style *font, char *label)
  852. /*
  853.  * Write out a Font style and label to file.
  854.  */
  855. {
  856.     return (fprintf(f, "%s %d %d %d %s Font, Size, Spacing, Leading\n",
  857.     font->name, font->size, font->spacing, font->leading, label) > 0);
  858. }
  859.  
  860. Boolean inside_write_slide_style(Slide_style *sf, FILE *f)
  861. /*
  862.  * Write slide style file.  Return FALSE if there's a problem.
  863.  */
  864. {
  865.     if (fputs(slide_style_magic, f) < Success)
  866.         return FALSE;
  867.     if (!write_rgb(f, &sf->background_color, "Background Color"))
  868.         return FALSE;
  869.     if (fprintf(f, "%s Background Image\n", sf->background_image) <= 0)
  870.         return FALSE;
  871.     if (!write_rgb(f, &sf->title_color, "Title Color"))
  872.         return FALSE;
  873.     if (!write_font_style(f, &sf->title_font, "Title"))
  874.         return FALSE;
  875.     if (fprintf(f, "%d Title Justification\n", sf->title_justification) <= 0)
  876.         return FALSE;
  877.     if (!write_xy(f, &sf->title_position, "Title Position"))
  878.         return FALSE;
  879.     if (!write_rgb(f, &sf->item_color, "Item Color"))
  880.         return FALSE;
  881.     if (!write_font_style(f, &sf->item_font, "Item"))
  882.         return FALSE;
  883.     if (fprintf(f, "%s Bullet Image\n", sf->bullet_image) <= 0)
  884.         return FALSE;
  885.     if (!write_rgb(f, &sf->bullet_color, "Bullet Color"))
  886.         return FALSE;
  887.     if (fprintf(f, "%s Logo Image\n", sf->logo_image) <= 0)
  888.         return FALSE;
  889.     if (!write_xy(f, &sf->logo_position, "Logo Position"))
  890.         return FALSE;
  891.     if (fprintf(f,"%i  AntiAliased Text and Logo (0 = off, 1 = on)\n"
  892.     , sf->antialias) <= 0)
  893.             return FALSE;
  894.     if (fprintf(f,"%i  Safe Titling (0 = off, 1 = on)\n"
  895.     , sf->safe_title) <= 0)
  896.             return FALSE;
  897.     if (fprintf(f,"%i  %i  %i  Text Animation Mode\n"
  898.     ,  sf->animode, sf->aniframes, sf->anispeed) <= 0)
  899.         return FALSE;
  900.     return TRUE;
  901. }
  902.  
  903.  
  904. Boolean write_slide_style(Slide_style *sf, char *file_name)
  905. /*
  906.  * Open slide style file and write it out.  Delete file and complain
  907.  * if there's a problem.
  908.  */
  909. {
  910.     FILE *f;
  911.     Boolean ok = FALSE;
  912.  
  913.     if ((f = must_open(file_name, "w")) != NULL)
  914.         {
  915.         ok = inside_write_slide_style(sf, f);
  916.         fclose(f);
  917.         if (!ok)
  918.             {
  919.             Qtext("Couldn't write slide style to %s, sorry", file_name);
  920.             DosDelete(file_name);
  921.             }
  922.         }
  923.     return ok;
  924. }
  925.  
  926. //-------------------------------------------------------------------------
  927. //     Style File Load Routines
  928. //-------------------------------------------------------------------------
  929.  
  930. Boolean verify_label(Line_file *file, char *buf, char *label)
  931. /*
  932.  * Verify that buf contains label.
  933.  */
  934. {
  935.     if (stristr(buf, label) == NULL)
  936.         {
  937.         expecting_got(file, label, buf);
  938.         return FALSE;
  939.         }
  940.     return TRUE;
  941. }
  942.  
  943. Boolean read_numbers_and_label(Line_file *file
  944. , int *nums, int num_count, char *label)
  945. /*
  946.  * Read in a line of form:
  947.  *     NN ... NN label
  948.  * into nums.    This is the basis for read_rgb and read_xy.
  949.  * Complain and return FALSE if there's a problem.
  950.  */
  951. {
  952.     char *buf = file->line_buf;
  953.  
  954.     if (!must_read_line(file))
  955.         return FALSE;
  956.     while (--num_count >= 0)
  957.         {
  958.         if (!next_number(file, &buf, nums))
  959.             return FALSE;
  960.         ++nums;
  961.         }
  962.     return verify_label(file, buf, label);
  963. }
  964.  
  965. Boolean read_rgb(Line_file *file, RGB *rgb, char *label)
  966. /*
  967.  * Read in a line of form:
  968.  *     NN NN NN label
  969.  * into an RGB triple.
  970.  * Complain and return FALSE if there's a problem.
  971.  */
  972. {
  973.     return read_numbers_and_label(file, (int *)rgb, 3, label);
  974. }
  975.  
  976. Boolean read_xy(Line_file *file, XY *xy, char *label)
  977. /*
  978.  * Read in a line of form:
  979.  *     NN NN label
  980.  * into an XY pair.
  981.  * Complain and return FALSE if there's a problem.
  982.  */
  983. {
  984.     return read_numbers_and_label(file, (int *)xy, 2, label);
  985. }
  986.  
  987. Boolean read_int_and_label(Line_file *file, int *result, char *label)
  988. /*
  989.  * Read in a line of form:
  990.  *     NN label
  991.  * into *result.
  992.  * Complain and return FALSE if there's a problem.
  993.  */
  994. {
  995.     return read_numbers_and_label(file, result, 1, label);
  996. }
  997.  
  998. Boolean read_name_and_label(Line_file *file, char *name, int name_size
  999. , char *label)
  1000. /*
  1001.  * Read in a line of form:
  1002.  *     name label
  1003.  *  into name.
  1004.  */
  1005. {
  1006.     char *buf = file->line_buf;
  1007.  
  1008.     if (!must_read_line(file))
  1009.         return FALSE;
  1010.     if (!next_string(file, &buf, name, name_size))
  1011.         {
  1012.         expecting_got(file, "a name", "<cr>");
  1013.         return FALSE;
  1014.         }
  1015.     return verify_label(file, buf, label);
  1016. }
  1017.  
  1018. Boolean read_font_line(Line_file *file, Font_style *fs, char *label)
  1019. {
  1020.     char *buf = file->line_buf;
  1021.  
  1022.     if (!must_read_line(file))
  1023.         return FALSE;
  1024.     if (!next_string(file, &buf, fs->name, sizeof(fs->name)))
  1025.         {
  1026.         expecting_got(file, "font name", "<cr>");
  1027.         return FALSE;
  1028.         }
  1029.     if (!next_number(file, &buf, &fs->size))
  1030.         return FALSE;
  1031.     if (!next_number(file, &buf, &fs->spacing))
  1032.         return FALSE;
  1033.     if (!next_number(file, &buf, &fs->leading))
  1034.         return FALSE;
  1035.     return verify_label(file, buf, label);
  1036. }
  1037.  
  1038. Boolean inside_read_slide_style(Slide_style *sf, Line_file *file)
  1039. /*
  1040.  * Read slide file.  Complain if there's a problem.
  1041.  */
  1042. {
  1043.     if (!must_read_line(file))
  1044.         return FALSE;
  1045.     if (strcmp(file->line_buf, slide_style_magic) != 0)
  1046.         {
  1047.         Qtext("%s is not a Show'em Slide Style file.", file->file_name);
  1048.         return FALSE;
  1049.         }
  1050.     if (!read_rgb(file, &sf->background_color, "Background Color"))
  1051.         return FALSE;
  1052.     if (!read_name_and_label(file
  1053.     ,  sf->background_image, sizeof(sf->background_image)
  1054.     ,  "Background Image"))
  1055.         return FALSE;
  1056.     if (!read_rgb(file, &sf->title_color, "Title Color"))
  1057.         return FALSE;
  1058.     if (!read_font_line(file, &sf->title_font, "Title Font"))
  1059.         return FALSE;
  1060.     if (!read_int_and_label(file
  1061.     , &sf->title_justification, "Title Justification"))
  1062.         return FALSE;
  1063.     if (!read_xy(file, &sf->title_position, "Title Position"))
  1064.         return FALSE;
  1065.     if (!read_rgb(file, &sf->item_color, "Item Color"))
  1066.         return FALSE;
  1067.     if (!read_font_line(file, &sf->item_font, "Item Font"))
  1068.         return FALSE;
  1069.     if (!read_name_and_label(file
  1070.     ,  sf->bullet_image, sizeof(sf->bullet_image),  "Bullet Image"))
  1071.         return FALSE;
  1072.     if (!read_rgb(file, &sf->bullet_color, "Bullet Color"))
  1073.         return FALSE;
  1074.     if (!read_name_and_label(file
  1075.     ,  sf->logo_image, sizeof(sf->logo_image),    "Logo Image"))
  1076.         return FALSE;
  1077.     if (!read_xy(file, &sf->logo_position, "Logo Position"))
  1078.         return FALSE;
  1079.     if (!read_int_and_label(file
  1080.     ,  &sf->antialias, "AntiAliased Text and Logo"))
  1081.             return FALSE;
  1082.     if (!read_int_and_label(file
  1083.     ,  &sf->safe_title, "Safe Titling"))
  1084.             return FALSE;
  1085.     {
  1086.     char *buf = file->line_buf;
  1087.  
  1088.     /* Read inline of format NN NN NN Text Animation Mode */
  1089.     if (!must_read_line(file))
  1090.         return FALSE;
  1091.     if (!next_number(file, &buf, &sf->animode))
  1092.         return FALSE;
  1093.     if (!next_number(file, &buf, &sf->aniframes))
  1094.         return FALSE;
  1095.     if (!next_number(file, &buf, &sf->anispeed))
  1096.         return FALSE;
  1097.     if (!verify_label(file, buf, "Text Animation Mode"))
  1098.         return FALSE;
  1099.     }
  1100. }
  1101.  
  1102. Boolean read_slide_style(Slide_style *sf, char *file_name)
  1103. /*
  1104.  * Open slide style file and read it.  Complain if there's 
  1105.  * a problem.
  1106.  */
  1107. {
  1108.     int ok = FALSE;
  1109.     Line_file file;
  1110.     char buf[256];
  1111.  
  1112.     if (line_file_open(&file, file_name, buf, sizeof(buf)))
  1113.         {
  1114.         ok = inside_read_slide_style(sf, &file);
  1115.         line_file_close(&file);
  1116.         }
  1117.             
  1118.     return ok;
  1119. }
  1120.  
  1121. //-------------------------------------------------------------------------
  1122. // Some Paragraph oriented stuff - to read in blank line separated sections
  1123. // of a text file.
  1124. //-------------------------------------------------------------------------
  1125.  
  1126. typedef struct paragraph
  1127.     {
  1128.     char **lines;
  1129.     int line_count;
  1130.     int line_alloc;
  1131.     int xmargin;
  1132.     int xoff;
  1133.     int yoff;
  1134.     int font_width;
  1135.     int font_height;
  1136.     int title_height;
  1137.     int in_item_dist;
  1138.     Boolean line_token;
  1139.     Boolean nopause;
  1140.     char clip_name[PATH_SIZE];
  1141.     } Paragraph;
  1142.  
  1143. Boolean init_paragraph(Paragraph *p)
  1144. /*
  1145.  * Set up empty paragraph.
  1146.  */
  1147. {
  1148.     p->line_alloc = 50;
  1149.     p->line_count = 0;
  1150.     p->xmargin = 0;
  1151.     p->xoff = 0;
  1152.     p->yoff = 0;
  1153.     p->font_width = 0;
  1154.     p->font_height = 0;
  1155.     p->title_height = 0;
  1156.     p->in_item_dist = 0;
  1157.     p->line_token = FALSE;
  1158.     p->nopause = FALSE;
  1159.     strcpy(p->clip_name,"none");
  1160.     
  1161.     if ((p->lines = need_memory(p->line_alloc * sizeof(char *))) == NULL)
  1162.         {
  1163.         return FALSE;
  1164.         }
  1165.     return TRUE;
  1166. }
  1167.  
  1168. void free_paragraph(Paragraph *p)
  1169. /*
  1170.  * Free all dynamic memory associated with paragraph.
  1171.  */
  1172. {
  1173.     int i;
  1174.  
  1175.     if (p->lines != NULL)
  1176.         {
  1177.         for (i=0; i<p->line_count; ++i)
  1178.             {
  1179.             if (p->lines[i] != NULL)
  1180.                 free(p->lines[i]);
  1181.             }
  1182.         free(p->lines);
  1183.         p->lines = NULL;
  1184.         }
  1185. }
  1186.  
  1187. Boolean paragraph_add_line(Paragraph *p, char *line)
  1188. /*
  1189.  * Add a line to paragraph.
  1190.  */
  1191. {
  1192.  
  1193.  
  1194.     if (p->line_count < p->line_alloc)
  1195.         {
  1196.         if (p->line_token == FALSE)
  1197.             {
  1198.             if ((p->lines[p->line_count] = strdup(line)) == NULL)
  1199.                 {
  1200.                 Qtext("Not enough memory for %s", line);
  1201.                 return FALSE;
  1202.                 }
  1203.             else
  1204.                 {
  1205.                 ++p->line_count;
  1206.                 return TRUE;
  1207.                 }
  1208.             }
  1209.         else
  1210.             {
  1211.             return TRUE;
  1212.             }
  1213.         }
  1214.     else
  1215.         {
  1216.         Qtext("Too many lines in paragraph");
  1217.         return FALSE;
  1218.         }
  1219. }
  1220.  
  1221.  
  1222.  
  1223. Boolean line_is_token(Paragraph *p, char *input, Line_file *file)
  1224. /*
  1225.  * Check line for a token
  1226.  */
  1227. {
  1228.     char *token;
  1229.     char *token_line;
  1230.     char *temp;
  1231.     char *line;
  1232.  
  1233.     int i;
  1234.     Boolean another_token;
  1235.  
  1236.     p->line_token = FALSE;
  1237.  
  1238.     if ((token = strdup(input)) == NULL)
  1239.         {
  1240.         Qtext("Not enough memory for %s", input);
  1241.         return FALSE;
  1242.         }
  1243.  
  1244.     if ((temp = strdup(input)) == NULL)
  1245.         {
  1246.         Qtext("Not enough memory for %s", input);
  1247.         return FALSE;
  1248.         }
  1249.  
  1250.     if (next_string(file, &temp, token, strlen(temp)+1))
  1251.         {
  1252.         ++temp;
  1253.         if ((token_line = strdup(temp)) == NULL)
  1254.             {
  1255.             Qtext("Not enough memory for %s", temp);
  1256.             return FALSE;
  1257.             }
  1258.         if (strlen(token_line) > 0)
  1259.             token_line[strlen(token_line)-1] = EOS;
  1260.         if (stricmp(token,"-nopause") == 0)
  1261.             {
  1262.             p->nopause = TRUE;
  1263.             p->line_token = TRUE;
  1264.             }
  1265.         if (stricmp(token, "-i") == 0)
  1266.             {
  1267.             strcpy(p->clip_name, token_line);
  1268.             p->line_token = TRUE;
  1269.             }
  1270.         if (stricmp(token, "-x") == 0)
  1271.             {
  1272.             strcpy(file->x_call, token_line);
  1273.             p->line_token = TRUE;
  1274.             }
  1275.         if (stricmp(token, "-b") == 0)
  1276.             {
  1277.             if (strlen(token_line) > 0)  //* Batch call must exist!
  1278.                 strcpy(file->bat_call, token_line);
  1279.             p->line_token = TRUE;
  1280.             }
  1281.         return TRUE;
  1282.         }
  1283.     return FALSE;
  1284. }
  1285.  
  1286.  
  1287. Boolean read_paragraph(Paragraph *p, Line_file *file)
  1288. /*
  1289.  * Read file until next blank line into paragraph.
  1290.  */
  1291. {
  1292.     /* First skip over any blank lines. */
  1293.     for (;;)
  1294.         {
  1295.         if (!read_line(file))
  1296.             return FALSE;
  1297.         if (skip_space(file->line_buf) != NULL)
  1298.             break;
  1299.         }
  1300.     /* Now go to next blank line or EOF. */
  1301.     for (;;)
  1302.         {
  1303.         if (!line_is_token(p, file->line_buf, file))
  1304.             return TRUE;
  1305.         if (!paragraph_add_line(p, file->line_buf))
  1306.             return TRUE;
  1307.         if (!read_line(file))
  1308.             return TRUE;
  1309.         if (skip_space(file->line_buf) == NULL)
  1310.             return TRUE;
  1311.         }
  1312. }
  1313.  
  1314. static Boolean init_and_read_paragraph(Paragraph *p, Line_file *lf)
  1315. /*
  1316.  * Initialize and read a paragraph.  Free things up and return FALSE
  1317.  * if there's a problem. 
  1318.  */
  1319. {
  1320. if (init_paragraph(p))
  1321.     {
  1322.     if (read_paragraph(p, lf))
  1323.         {
  1324.         return TRUE;
  1325.         }
  1326.     free_paragraph(p);
  1327.     }
  1328. return FALSE;
  1329. }
  1330.  
  1331. //-------------------------------------------------------------------------
  1332. // File naming routines.
  1333. //-------------------------------------------------------------------------
  1334.  
  1335. static void batch_to_base_name(char *batch_name, char *base_name)
  1336. /*
  1337.  * Convert the .bat file name to a base name to use as the start
  1338.  * of the names for .scr and .flc files.
  1339.  */
  1340. {
  1341. char dev[4], dir[PATH_SIZE], file[10], suff[5];
  1342. fnsplit(batch_name, dev, dir, file, suff);
  1343. file[5] = 0;    /* Leave room for number. */
  1344. sprintf(base_name, "%s%s%s", dev, dir, file);
  1345. }
  1346.  
  1347. static void base_to_script_name(char *base_name, char *script_name
  1348. , int script_num)
  1349. /*
  1350.  * Go from path\xxxxx to path\xxxxxNNN.scr
  1351.  */
  1352. {
  1353. sprintf(script_name, "%s%03d.SCR", base_name, script_num);
  1354. }
  1355.  
  1356. static void base_name_to_slide_start(char *base_name
  1357. , char *slide_start, int slide_ix)
  1358. /*
  1359.  * Go from path\xxxxx to path\xxxxxNN
  1360.  */
  1361. {
  1362. sprintf(slide_start, "%s%02d", base_name, slide_ix);
  1363. }
  1364.  
  1365. static void slide_flic_name(char *flic_name, char *slide_name, int line_ix)
  1366. /*
  1367.  * Go from path\xxxxxNN to path\xxxxxNNa.FLC
  1368.  */
  1369. {
  1370. sprintf(flic_name, "%s%c.FLC", slide_name, 'A'+line_ix);
  1371. }
  1372.  
  1373. //-------------------------------------------------------------------------
  1374. // Drawing routines
  1375. //-------------------------------------------------------------------------
  1376.  
  1377. typedef struct
  1378. /* Keep track of the color registers we want to draw in
  1379.  * (as opposed to the RGB values)
  1380.  */
  1381.     {
  1382.     int title;
  1383.     int item;
  1384.     int bullet;
  1385.     } Drawing_colors;
  1386.  
  1387.  
  1388. void find_drawing_colors(Drawing_colors *dc, Slide_style *sf)
  1389. /*
  1390.  * Find colors to draw slide in from RGB values in Slide_style. 
  1391.  */
  1392. {
  1393.     dc->title = ClosestColorInScreen(GetPicScreen()
  1394.     , sf->title_color.r, sf->title_color.g, sf->title_color.b);
  1395.     dc->item = ClosestColorInScreen(NULL
  1396.     , sf->item_color.r, sf->item_color.g, sf->item_color.b);
  1397.     dc->bullet = ClosestColorInScreen(NULL
  1398.     , sf->bullet_color.r, sf->bullet_color.g, sf->bullet_color.b);
  1399. }
  1400.  
  1401. static int find_intermediate_value(double percent, int start, int end)
  1402. /*
  1403.  *  Return a color percent between start and end.
  1404.  */
  1405. {
  1406.     int diff = end - start;
  1407.     return (start + percent*diff);
  1408. }
  1409.  
  1410. static void find_intermediate_color(RGB *result, double percent
  1411. , RGB *start, RGB *end)
  1412. /*
  1413.  *  Put a color percent between start and end into result
  1414.  */
  1415. {
  1416.     result->r = find_intermediate_value(percent, start->r, end->r);
  1417.     result->g = find_intermediate_value(percent, start->g, end->g);
  1418.     result->b = find_intermediate_value(percent, start->b, end->b);
  1419. }
  1420.  
  1421. static void ramp_range(RGB *start_color, RGB *stop_color)
  1422. /*
  1423.  * Puts a color ramp into the current range.
  1424.  */
  1425. {
  1426.     int *cluster;
  1427.     int ccount;
  1428.     int i;
  1429.     double percent;
  1430.     RGB intermediate;
  1431.     Errcode err;
  1432.  
  1433.     if ((err = GetCluster(&ccount, &cluster)) < Success)
  1434.         Qerror(err, "Can't GetCluster");
  1435.     else
  1436.         {
  1437.         for (i=0; i<ccount; ++i)
  1438.             {
  1439.             percent = (double)i/(double)(ccount-1);
  1440.             find_intermediate_color(&intermediate, percent
  1441.             ,  start_color, stop_color);
  1442.             SetColorMap(cluster[i]
  1443.             , intermediate.r, intermediate.g, intermediate.b);
  1444.             }
  1445.         free(cluster);
  1446.         }
  1447. }
  1448.  
  1449. static void set_color_range(int start, int stop
  1450. , RGB *start_color, RGB *stop_color)
  1451. /*
  1452.  * This puts the colors from start to stop into the cluster.
  1453.  *  Then it makes a gradient in those colors from start_color to
  1454.  *  stop_color.
  1455.  */
  1456. {
  1457.     int *cluster;
  1458.     int i;
  1459.     int ccount = stop-start+1;
  1460.  
  1461.     if ((cluster = need_memory(ccount * sizeof(int))) != NULL)
  1462.         {
  1463.         for (i=0; i<ccount; ++i)
  1464.             {
  1465.             cluster[i] = start+i;
  1466.             }
  1467.         SetCluster(ccount, cluster);
  1468.         free(cluster);
  1469.         }
  1470.     ramp_range(start_color, stop_color);
  1471. }
  1472.  
  1473. static Boolean is_solid(char *name)
  1474. {
  1475. return stricmp(name, "solid") == 0;
  1476. }
  1477.  
  1478. static Boolean is_gradient(char *name)
  1479. {
  1480. return stricmp(name, "gradient") == 0;
  1481. }
  1482.  
  1483. static Errcode change_flic_size(int width, int height)
  1484. /*
  1485.  * Check to see if current flic is width x height.  If not do a
  1486.  * resize reset to force it.
  1487.  */
  1488. {
  1489. int ow, oh;
  1490.  
  1491. GetSize(&ow, &oh);
  1492. if (ow != width || oh != height)
  1493.     {
  1494.     return ResizeReset(width, height);
  1495.     }
  1496. else
  1497.     return Success;
  1498. }
  1499.  
  1500. static Boolean preload_background(Slide_style *sf)
  1501. /*
  1502.  * Draw the background into swap screen.
  1503.  */
  1504. {
  1505.     char *name = sf->background_image;
  1506.     RGB *col = &sf->background_color;
  1507.     static RGB black = {0,0,0};
  1508.     int phy_width, phy_height;
  1509.     int back_color_index;
  1510.     static struct optPos op;
  1511.  
  1512.     GetPhysicalSize(&phy_width, &phy_height);
  1513.     if (sf->safe_title == TRUE)
  1514.         {
  1515.         slide_width = phy_width*0.9;
  1516.         slide_height = phy_height*0.9;
  1517.         }
  1518.     else
  1519.         {
  1520.         if ((phy_width > slide_width) || (phy_height > slide_height))
  1521.             {
  1522.             if (change_flic_size(phy_width, phy_height) < Success)
  1523.                 return FALSE;
  1524.             slide_width = phy_width;
  1525.             slide_height = phy_height;
  1526.             }
  1527.         }
  1528.  
  1529.     SetFilled(TRUE);
  1530.  
  1531.     if (is_solid(name))
  1532.         {
  1533.         if (sf->safe_title == TRUE)
  1534.             {
  1535.             if (change_flic_size(slide_width, slide_height) < Success)
  1536.                 return FALSE;
  1537.             }
  1538.         else
  1539.             {
  1540.             GetPhysicalSize(&phy_width, &phy_height);
  1541.             if (change_flic_size(phy_width, phy_height) < Success)
  1542.                 return FALSE;
  1543.             }
  1544.         Clear();
  1545.         back_color_index = ClosestColorInScreen(NULL, sf->background_color.r
  1546.         , sf->background_color.g, sf->background_color.b);
  1547.         SetColor(back_color_index);
  1548.         SetInk("Opaque");
  1549.         Box(0, 0, slide_width, slide_height);
  1550.         }
  1551.     else if (is_gradient(name))
  1552.         {
  1553.         if (sf->safe_title == TRUE)
  1554.             {
  1555.             if (change_flic_size(slide_width, slide_height) < Success)
  1556.                 return FALSE;
  1557.             }
  1558.         else
  1559.             {
  1560.             GetPhysicalSize(&phy_width, &phy_height);
  1561.             if (change_flic_size(phy_width, phy_height) < Success)
  1562.                 return FALSE;
  1563.             }
  1564.         set_color_range(0, 63,  &black, col);
  1565.         SetInk("V Grad");
  1566.         Box(0, 0, slide_width, slide_height);
  1567.         }
  1568.     else
  1569.         {
  1570.         if (sf->safe_title == TRUE)         //* Shrink the visible screen by 90%
  1571.             {
  1572.             int cmap[256*3];
  1573.             GetPhysicalSize(&phy_width, &phy_height);
  1574.             if (change_flic_size(phy_width, phy_height) < Success)
  1575.                 return FALSE;
  1576.             LoadPic(name);
  1577.             GetScreenColorMap(GetPicScreen(), cmap);
  1578.             OptClearPos();
  1579.             OptDefaultCenters();
  1580.             OptGetPos(&op);
  1581.             op.bp = 90;             //* new size to be 90% of original
  1582.             op.bq = 100;
  1583.             OptSetPos(&op);
  1584.             OptSetElement(EL_SCREEN);
  1585.             OptToFrame(1);
  1586.             CelClip();
  1587.             if (change_flic_size(slide_width, slide_height) < Success)
  1588.                 return FALSE;
  1589.             SetScreenColorMap(GetPicScreen(), cmap);
  1590.             CelMoveTo(slide_width/2, slide_height/2);
  1591.             CelPaste();
  1592.             }
  1593.         else
  1594.             {
  1595.             LoadPic(name);
  1596.             }
  1597.         }
  1598.     SwapClip();
  1599.     return SwapExists();
  1600. }
  1601.  
  1602. static Boolean draw_clip(Paragraph *p)
  1603. /*
  1604.  * Draw the clip
  1605.  */
  1606. {
  1607.     int x,y,clipw,cliph;
  1608.  
  1609.     if (stricmp(p->clip_name, "none") == 0)
  1610.         return TRUE;
  1611.     if (LoadCel(p->clip_name) >= Success)
  1612.         {
  1613.         GetScreenSize( GetCelScreen(), &clipw, &cliph);
  1614.         x = clipw/2 + (slide_width - clipw)/2;
  1615.         y = p->title_height + cliph/2 + 
  1616.         (slide_height - p->title_height - cliph)/2;
  1617.         CelMoveTo(x, y);
  1618.         SetInk("opaque");
  1619.         CelPaste();
  1620.         return TRUE;
  1621.         }
  1622.     else
  1623.         {
  1624.         Qtext("Could not load clip file:n\"%s\"", p->clip_name); 
  1625.         return FALSE;
  1626.         }
  1627. }
  1628.  
  1629. static Boolean draw_logo(Slide_style *sf)
  1630. /*
  1631.  * Draw the logo
  1632.  */
  1633. {
  1634.     XY *pos;
  1635.     int logow,logoh;
  1636.  
  1637.     if (stricmp(sf->logo_image, "none") == 0)
  1638.         return TRUE;
  1639.     if (LoadCel(sf->logo_image) >= Success)
  1640.         {
  1641.         pos = &sf->logo_position;
  1642.         GetScreenSize( GetCelScreen(), &logow, &logoh);
  1643.         CelMoveTo(pos->x, pos->y);
  1644.         SetInk("opaque");
  1645.         CelPaste();
  1646.         if (sf->antialias)
  1647.             {
  1648.             PicDirtied();
  1649.             SetInk("unzag");
  1650.             CelPaste();
  1651.             }
  1652.         return TRUE;
  1653.         }
  1654.     else
  1655.         return FALSE;
  1656. }
  1657.  
  1658.  
  1659. static void set_shadow(int strength)
  1660. /*
  1661.  * Set up ink, etc for shadow.
  1662.  */
  1663. {
  1664.     SetInk("Dark");
  1665.     SetInkStrength(strength);
  1666. }
  1667.  
  1668. enum bullet_type {BT_NONE, BT_CEL, BT_CIRCLE};
  1669. typedef struct 
  1670.     {
  1671.     enum bullet_type type;  /* Type of bullet. */
  1672.     RGB bullet_color;         /* Bullet Color. */
  1673.     int width, height;        /* Dimensions of bullet. */
  1674.     int text_xoff;             /* Space from center of bullet to where 
  1675.                                      * text starts */
  1676.     } Bullet_data;
  1677.  
  1678. void find_bullet(Bullet_data *bd, Slide_style *sf, Paragraph *pb)
  1679. /*
  1680.  * This will load the bullet into the Cel if possible
  1681.  * otherwise complain and revert to the circle bullet.
  1682.  * Returns type.
  1683.  */
  1684. {
  1685.     if (stricmp(sf->bullet_image, "none") == 0)
  1686.         {
  1687.         bd->width = bd->height = 0;
  1688.         bd->text_xoff = 0;
  1689.         bd->type = BT_NONE;
  1690.         }
  1691.     else if (stricmp(sf->bullet_image, "circle") == 0)
  1692.         {
  1693.         bd->width = bd->height = pb->font_height/2;
  1694.         bd->text_xoff = bd->width/2 + pb->font_width;
  1695.         bd->type = BT_CIRCLE;
  1696.         }
  1697.     else
  1698.         {
  1699.         if (Success > LoadCel(sf->bullet_image))
  1700.             {  /* On error revert to circle. */
  1701.             strcpy(sf->bullet_image, "circle");
  1702.             find_bullet(bd, sf, pb);
  1703.             }
  1704.         else
  1705.             {
  1706.             GetScreenSize(GetCelScreen(), &bd->width, &bd->height);
  1707.             bd->text_xoff = bd->width/2 + pb->font_width;
  1708.             bd->type = BT_CEL;
  1709.             }
  1710.         }
  1711. }
  1712.  
  1713. void draw_bullet(Slide_style *sf, Bullet_data *bd, int xoff, int yoff
  1714. , int color)
  1715. /*
  1716.  * Draw a bullet centered at xoff, yoff.  Should be called shortly after
  1717.  * find_bullet() - or at least before you reload the cel.
  1718.  */
  1719. {
  1720.     switch (bd->type)
  1721.         {
  1722.         case BT_CIRCLE:
  1723.             {
  1724.             int rad = bd->width/2;
  1725.             set_shadow(50);
  1726.             Circle(xoff+shadow_xoff, yoff+shadow_yoff, rad);
  1727.             SetInk("Opaque");
  1728.             SetColor(color);
  1729.             Circle(xoff, yoff, rad);
  1730.             if (sf->antialias)
  1731.                 {
  1732.                 PicDirtied();
  1733.                 SetInk("unzag");
  1734.                 Circle(xoff, yoff, rad);
  1735.                 }
  1736.             }
  1737.             break;
  1738.         case BT_CEL:
  1739.             CelMoveTo(xoff, yoff);
  1740.             SetInk("Opaque");
  1741.             CelPaste();
  1742.             if (sf->antialias)
  1743.                 {
  1744.                 PicDirtied();
  1745.                 SetInk("unzag");
  1746.                 CelPaste();
  1747.                 }
  1748.             break;
  1749.         case BT_NONE:
  1750.         default:
  1751.             break;
  1752.         }
  1753. }
  1754.  
  1755. static void draw_shadow_and_antialias(int x, int y, int w, int color
  1756. , int shadow_x, int shadow_y, char *string, Boolean antialias)
  1757. /*
  1758.  * Draw text and it's drop shadow.  Then antialias if desired. 
  1759.  */
  1760. {
  1761.     /* Draw drop-shadow. */
  1762.     set_shadow(50);
  1763.     WordWrap(x+shadow_x, y+shadow_y, w, slide_height, string);
  1764.  
  1765.     /* Draw text proper. */
  1766.     SetInk("Opaque");
  1767.     SetColor(color);
  1768.     WordWrap(x, y, w, slide_height, string);
  1769.  
  1770.     /* Do anti-aliasing. */
  1771.     if (antialias)
  1772.         {
  1773.         PicDirtied();
  1774.         SetInk("unzag");
  1775.         WordWrap(x, y, w, slide_height, string);
  1776.         }
  1777. }
  1778.  
  1779. static int draw_still_text( int x_start, int y_start, int w, int text_color
  1780. , char *string, int justification, Boolean antialias)
  1781. /*
  1782.  * Show text with a drop shadow.  Returns the # of lines of text
  1783.  * drawn.
  1784.  */
  1785. {
  1786.     SetJustify(justification);
  1787.     draw_shadow_and_antialias(x_start, y_start, w, text_color
  1788.     , shadow_xoff, shadow_yoff, string, antialias);
  1789.     return WordWrapCountLines(w, string);
  1790. }
  1791.  
  1792. typedef struct jiffy_timer
  1793. /* Structure to help us wait until a certain number of jiffies have passed */
  1794.     {
  1795.     int jiffy_count;
  1796.     long start_millis;
  1797.     } Jiffy_timer;
  1798.  
  1799. void start_jiffy_timer(Jiffy_timer *this, int jiffy_count)
  1800. /*
  1801.  * Call this at start of time interval.
  1802.  */
  1803. {
  1804.     this->jiffy_count = jiffy_count;
  1805.     this->start_millis = Clock1000();
  1806. }
  1807.  
  1808. Boolean wait_jiffy_timer(Jiffy_timer *this)
  1809. /*
  1810.  * Call this to wait until interval has passed.
  1811.  * Return FALSE if escape key pressed in the meantime.
  1812.  */
  1813. {
  1814. long stop_millis = (this->jiffy_count * 1000L / 70) + this->start_millis;
  1815. int x,y,left,right,key;
  1816.  
  1817. while (stop_millis > Clock1000())
  1818.     {
  1819.     PollInput(&x,&y,&left,&right,&key);
  1820.     if ((key&0xff) == ESCAPE_KEY)
  1821.         return FALSE;
  1822.     }
  1823. return TRUE;
  1824. }
  1825.  
  1826. typedef struct behind    
  1827. /* Keep track of area behind animation. */
  1828.     {
  1829.     char *pixels;
  1830.     int x, y;
  1831.     int width, height;
  1832.     } Behind;
  1833.  
  1834. Boolean init_behind(Behind *b, int x, int y, int width, int height)
  1835. /*
  1836.  * Set up data structure to store a rectangular area of the screen
  1837.  * and allocate memory buffer to hold pixels.
  1838.  */
  1839. {
  1840. b->width = width;
  1841. b->height = height;
  1842. b->x = x;
  1843. b->y = y;
  1844. if ((b->pixels = need_memory(width*height*PIXEL_SIZE)) == NULL)
  1845.     return FALSE;
  1846. return TRUE;
  1847. }
  1848.  
  1849. Boolean save_behind(Behind *b)
  1850. /*
  1851.  * Back up a portion of the screen. 
  1852.  */
  1853. {
  1854. GetBlock(GetPicScreen(), b->pixels, b->x, b->y, b->width, b->height);
  1855. }
  1856.  
  1857. Boolean restore_behind(Behind *b)
  1858. /*
  1859.  * Restore a portion of the screen.
  1860.  */
  1861. {
  1862. SetBlock(GetPicScreen(), b->pixels, b->x, b->y, b->width, b->height);
  1863. }
  1864.  
  1865. Boolean free_behind(Behind *b)
  1866. /*
  1867.  * Free up pixel memory buffer.
  1868.  */
  1869. {
  1870. if (b->pixels != NULL)
  1871.     {
  1872.     free(b->pixels);
  1873.     b->pixels = NULL;
  1874.     }
  1875. }
  1876.  
  1877.  
  1878. static int draw_scroll_text( int x_start, int y_start, int w
  1879. , int shadow_x, int shadow_y
  1880. , int text_color, char *string, Boolean antialias
  1881. , int frame_count, int flic_speed, Boolean save)
  1882. /*
  1883.  * Show text with a drop shadow.  Returns the # of lines of text
  1884.  * drawn.
  1885.  */
  1886. {
  1887.     double dist;                            //* animation offset distance
  1888.     double dx;                              //* incremental distance per frame
  1889.     int nf;                              //* frame index
  1890.     int line_count = WordWrapCountLines(w, string);
  1891.     int ok = TRUE;
  1892.  
  1893.     /* Calculate size of word-wrap box. */
  1894.     w = slide_width*0.95 - x_start;
  1895.  
  1896.     /* Draw text proper. */
  1897.  
  1898.     SetJustify(0);
  1899.     dist = slide_width - x_start;
  1900.     dx = dist / frame_count;
  1901.     if (save)
  1902.         {
  1903.         for(nf=0;nf<frame_count; nf++)
  1904.             {
  1905.             dist -= dx;
  1906.             NextFrame();
  1907.             draw_shadow_and_antialias(x_start+dist, y_start, w, text_color
  1908.             , shadow_x, shadow_y, string, antialias);
  1909.             }
  1910.         }
  1911.     else
  1912.         {
  1913.         Behind behind;
  1914.         Jiffy_timer timer;
  1915.  
  1916.         if (init_behind(&behind, x_start, y_start
  1917.         , slide_width - x_start, line_count * FontHeight() + shadow_y))
  1918.             {
  1919.             save_behind(&behind);
  1920.             for(nf=0;nf<frame_count; nf++)
  1921.                 {
  1922.                 start_jiffy_timer(&timer, flic_speed);
  1923.                 dist -= dx;
  1924.                 restore_behind(&behind);
  1925.                 draw_shadow_and_antialias(x_start+dist, y_start, w, text_color
  1926.                 , shadow_x, shadow_y, string, antialias);
  1927.                 if (!wait_jiffy_timer(&timer))
  1928.                     {
  1929.                     ok = FALSE;
  1930.                     break;
  1931.                     }
  1932.                 }
  1933.             free_behind(&behind);
  1934.             }
  1935.         }
  1936.     return ok;
  1937. }
  1938.  
  1939. static int draw_transparent_and_shadowed(int x, int y, int w, int color
  1940. , int shadow_x, int shadow_y
  1941. , char *string, Boolean antialias,  int percent)
  1942. /*
  1943.  * Draw transparent text and an even more transparent drop shadow.
  1944.  */
  1945. {
  1946. /* Draw shadow. */
  1947. set_shadow(percent/2);
  1948. WordWrap(x+shadow_x, y+shadow_y, w, slide_height, string);
  1949.  
  1950. SetInk("glass");
  1951. SetInkStrength(percent);
  1952. SetColor(color);
  1953. WordWrap(x, y, w, slide_height, string);
  1954.  
  1955. /* Do anti-aliasing. */
  1956. if (antialias)
  1957.     {
  1958.     PicDirtied();
  1959.     SetInk("unzag");
  1960.     WordWrap(x, y, w, slide_height, string);
  1961.     }
  1962. }
  1963.  
  1964. static int draw_fade_text( int x_start, int y_start, int w
  1965. , int shadow_x, int shadow_y
  1966. , int text_color, char *string, Boolean antialias
  1967. , int frame_count, int flic_speed, Boolean save)
  1968. /*
  1969.  * Draw text fading in.  (Either to file or by preview.)
  1970.  */
  1971. {
  1972. double trans;                          //* ink strength for glass ink
  1973. double tx;                              //* ink strength increment per frame
  1974. int nf;                                    //* frame index
  1975. int line_count = WordWrapCountLines(w, string);
  1976. Boolean ok = TRUE;
  1977.  
  1978. SetJustify(0);
  1979. tx = 100 / frame_count;
  1980. trans = 0;
  1981. if (save)
  1982.     {
  1983.     for(nf=0;nf<frame_count; nf++)
  1984.         {
  1985.         trans += tx;
  1986.         NextFrame();
  1987.         draw_transparent_and_shadowed(x_start, y_start, w, text_color
  1988.         , shadow_x, shadow_y, string, antialias, trans);
  1989.         }
  1990.     }
  1991. else
  1992.     {
  1993.     Behind behind;
  1994.     Jiffy_timer timer;
  1995.  
  1996.     if (init_behind(&behind, x_start, y_start
  1997.     , slide_width - x_start, line_count * FontHeight() + shadow_y))
  1998.         {
  1999.         save_behind(&behind);
  2000.         for(nf=0;nf<frame_count; nf++)
  2001.             {
  2002.             start_jiffy_timer(&timer, flic_speed);
  2003.             trans += tx;
  2004.             restore_behind(&behind);
  2005.             draw_transparent_and_shadowed(x_start, y_start, w, text_color
  2006.             , shadow_x, shadow_y, string, antialias, trans);
  2007.             if (!wait_jiffy_timer(&timer))
  2008.                 {
  2009.                 ok = FALSE;
  2010.                 break;
  2011.                 }
  2012.             }
  2013.         free_behind(&behind);
  2014.         }
  2015.     }
  2016. return ok;
  2017. }
  2018.  
  2019.  
  2020.  
  2021. static Boolean draw_still_items(Slide_style *sf, Drawing_colors *ci
  2022. , Paragraph *pi, Bullet_data *bi, Boolean save, char *base_name)
  2023. {
  2024. Boolean ok = TRUE;
  2025. int i;
  2026. int actual_lines;
  2027. char save_file[PATH_SIZE];
  2028. RGB *col = &sf->background_color;
  2029. int x,y,l,r,key;
  2030. static struct optPos op;
  2031.  
  2032. SetJustify(0);
  2033.  
  2034.  
  2035. for (i=1; i<=pi->line_count-1; ++i)
  2036.   {
  2037.   draw_bullet(sf, bi
  2038.   , pi->xmargin, pi->yoff+pi->font_height/2, ci->bullet);
  2039.   actual_lines = draw_still_text(pi->xoff, pi->yoff
  2040.   , slide_width*0.95 - pi->xoff, ci->item, pi->lines[i]
  2041.   , 0 , sf->antialias);
  2042.   pi->yoff += pi->in_item_dist + actual_lines*pi->font_height;
  2043.   }
  2044. if(save)
  2045.     {
  2046.     slide_flic_name(save_file,  base_name, 0);
  2047.     printf("Saving file %s to disk", save_file);
  2048.     fprintf(script
  2049.     , "%s -p 0 -t fadein color(%d,%d,%d) fadeout color(%d,%d,%d)\n"
  2050.     , save_file
  2051.     , col->r/2, col->g/2, col->b/2
  2052.     , col->r/2, col->g/2, col->b/2);
  2053.     if (SaveFlic(save_file) < Success)
  2054.         ok = FALSE;
  2055.     unprintf();
  2056.     }
  2057. return ok;
  2058. }
  2059.  
  2060. static Boolean wait_for_escape()
  2061. /*
  2062.  * Waits for next click.  Returns TRUE if it was a keypress <esc>
  2063.  */
  2064. {
  2065. int x,y,left,right, key;
  2066. WaitClick(&x,&y,&left,&right,&key);
  2067. return (key&0xff) == ESCAPE_KEY;
  2068. }
  2069.  
  2070. static Boolean draw_anim_items(Slide_style *sf, Drawing_colors *ci
  2071. , Paragraph *pi, Bullet_data *bi, Boolean save, char *base_name)
  2072. /*
  2073.  * Do drawing and possibly more of animated slide.
  2074.  */
  2075. {
  2076. int i = 0;
  2077. int actual_lines;
  2078. int item_count;
  2079. char save_file[PATH_SIZE];
  2080. RGB *col = &sf->background_color;
  2081. static struct optPos op;
  2082. int item_width = slide_width * 0.95 - pi->xoff;
  2083.  
  2084. item_count = pi->line_count;
  2085.  
  2086. if(save)
  2087.     {
  2088.     slide_flic_name(save_file,  base_name, 0);
  2089.     printf("Saving %s to disk",save_file);
  2090.     if (SaveFlic(save_file) < Success)
  2091.         return FALSE;
  2092.     unprintf();
  2093.  
  2094.     if((item_count == 1) && (pi->nopause == TRUE))
  2095.         {
  2096.         fprintf(script
  2097.         , "%s -p 1 -t fadein color(%d,%d,%d) fadeout color(%d,%d,%d)\n"
  2098.         , save_file
  2099.         , col->r/2, col->g/2, col->b/2
  2100.         , col->r/2, col->g/2, col->b/2);
  2101.         }
  2102.     else if((item_count == 1) && (pi->nopause == FALSE))
  2103.         {
  2104.         fprintf(script
  2105.         , "%s -p 0 -t fadein color(%d,%d,%d) fadeout color(%d,%d,%d)\n"
  2106.         , save_file
  2107.         , col->r/2, col->g/2, col->b/2
  2108.         , col->r/2, col->g/2, col->b/2);
  2109.         }
  2110.     else if((item_count > 1) && (pi->nopause == TRUE))
  2111.         {
  2112.         fprintf(script
  2113.         , "%s -p 1 -t fadein color(%d,%d,%d) \n"
  2114.         , save_file
  2115.         , col->r/2, col->g/2, col->b/2);
  2116.         }
  2117.     else if((item_count > 1) && (pi->nopause == FALSE))
  2118.         {
  2119.         fprintf(script
  2120.         , "%s -p 0 -t fadein color(%d,%d,%d)\n"
  2121.         , save_file
  2122.         , col->r/2, col->g/2, col->b/2);
  2123.         }
  2124.     }
  2125. for (i=1; i<=item_count-1; i++)
  2126.     {
  2127.     draw_bullet(sf, bi
  2128.     , pi->xmargin, pi->yoff+pi->font_height/2, ci->bullet);
  2129.     if (save)
  2130.         InsertFrames(sf->aniframes); 
  2131.     if(sf->animode == AM_SCROLL)
  2132.         {
  2133.         if (!draw_scroll_text(pi->xoff, pi->yoff, item_width
  2134.         , shadow_xoff, shadow_yoff, ci->item
  2135.         , pi->lines[i], sf->antialias, sf->aniframes, sf->anispeed, save))
  2136.             return FALSE;
  2137.         }
  2138.     else if(sf->animode == AM_FADE)
  2139.         {
  2140.         if (!draw_fade_text(pi->xoff, pi->yoff, item_width
  2141.         , shadow_xoff, shadow_yoff, ci->item
  2142.         , pi->lines[i], sf->antialias, sf->aniframes, sf->anispeed, save))
  2143.             return FALSE;
  2144.         }
  2145.     actual_lines = WordWrapCountLines(item_width, pi->lines[i]);
  2146.     pi->yoff += pi->in_item_dist + actual_lines*pi->font_height;
  2147.     if (save)
  2148.         {
  2149.         slide_flic_name(save_file,  base_name, i);
  2150.         printf("Saving flic %s to disk",save_file);
  2151.         if (SaveFlic(save_file) < Success)
  2152.             return FALSE;
  2153.         NextFrame();
  2154.         DeleteFrames(sf->aniframes);          //* delete previous frames 
  2155.         BackFrame();                        //* now return to the last frame
  2156.  
  2157.         if(i == item_count-1)
  2158.             {
  2159.             fprintf(script
  2160.             , "%s -p 0 -s %i -t fadeout color(%d,%d,%d)\n"
  2161.             , save_file, sf->anispeed
  2162.             , col->r/2, col->g/2, col->b/2);
  2163.             }
  2164.         else
  2165.             {
  2166.             if (pi->nopause)
  2167.                 {
  2168.                 fprintf(script
  2169.                 , "%s -s %i \n"
  2170.                 , save_file, sf->anispeed);
  2171.                 }
  2172.             else
  2173.                 {
  2174.                 fprintf(script
  2175.                 , "%s -p 0 -s %i \n"
  2176.                 , save_file, sf->anispeed);
  2177.                 }
  2178.             }
  2179.         unprintf();
  2180.         }
  2181.     else if (!pi->nopause && i != item_count - 1)
  2182.         {
  2183.         if (wait_for_escape())
  2184.             {
  2185.             unprintf();
  2186.             return FALSE;
  2187.             }
  2188.         unprintf();
  2189.         }
  2190.     }
  2191. return TRUE;
  2192. }
  2193.  
  2194. static Boolean draw_one_slide(Slide_style *sf, Line_file *file
  2195. , enum AnimMode mode, Boolean save, char *base_name)
  2196. /*
  2197.  * This draws a paragraph according to the slide style.
  2198.  * Calculates all the x,y positions to draw everything, and draws
  2199.  * the standard slide, with the title.
  2200.  */
  2201. {
  2202.     Paragraph p;
  2203.     Boolean ok = FALSE;
  2204.     Drawing_colors colors;
  2205.     Bullet_data b;
  2206.     int title_font_height;
  2207.     int item_total_lines;
  2208.     int empty_height;
  2209.     int i;
  2210.  
  2211.     /*
  2212.      * Load in next paragraph from input file and
  2213.      * display it.
  2214.      */
  2215.  
  2216.     
  2217.     find_drawing_colors(&colors, sf);
  2218.     if (init_and_read_paragraph(&p, file))
  2219.         {
  2220.         if (p.line_count >= 1)
  2221.             {
  2222.             /* Draw background. */
  2223.             CopyScreen(GetSwapScreen(), GetPicScreen()); 
  2224.             PicDirtied ();
  2225.             
  2226.             /* Draw title. */
  2227.             set_font_style(&sf->title_font);
  2228.             title_font_height = FontHeight();
  2229.             p.title_height 
  2230.             = WordWrapCountLines(get_title_width(sf), p.lines[0]);
  2231.             p.title_height *=title_font_height;
  2232.             p.title_height +=sf->title_position.y;
  2233.  
  2234.             draw_clip(&p);
  2235.             draw_logo(sf);
  2236.  
  2237.             draw_still_text(sf->title_position.x
  2238.             , sf->title_position.y, get_title_width(sf), colors.title
  2239.             , p.lines[0], sf->title_justification, sf->antialias);
  2240.  
  2241.             set_font_style(&sf->item_font);
  2242.             p.font_height = FontHeight();
  2243.             p.font_width = StringWidth("x");
  2244.             p.xmargin = slide_width/10;
  2245.             
  2246.             find_bullet(&b, sf, &p);
  2247.  
  2248.             /* figure empty_height - the amount of the screen that has no 
  2249.              * text or title in it. */
  2250.             p.xoff = p.xmargin + b.text_xoff;  /* Left edge of text. */
  2251.             item_total_lines = 0;
  2252.             for (i=1; i<=p.line_count-1; ++i)
  2253.                 {
  2254.                 item_total_lines 
  2255.                 += WordWrapCountLines(slide_width*0.95-p.xoff, p.lines[i]);
  2256.                 }
  2257.             empty_height = (slide_height*0.95) - p.title_height 
  2258.             - item_total_lines * p.font_height;
  2259.  
  2260.             /* Calculate the inter_item_distance and where to start item 
  2261.              * text vertically. 
  2262.              * We'll leave a margin 1/3 again the space between items
  2263.              * between the title and the items. */
  2264.             p.in_item_dist = (empty_height)/(p.line_count+1);
  2265.             p.yoff = p.title_height 
  2266.             + (empty_height - p.in_item_dist*(p.line_count-2))/3;
  2267.  
  2268.             switch(mode)
  2269.                 {
  2270.                 case AM_STILL:
  2271.                     if(!draw_still_items(sf
  2272.                     , &colors, &p, &b, save, base_name))
  2273.                         return FALSE;
  2274.                     break;
  2275.                 case AM_SCROLL:
  2276.                     if(!draw_anim_items(sf
  2277.                     , &colors, &p, &b, save, base_name))
  2278.                         return FALSE;
  2279.                     break;
  2280.                 case AM_FADE:
  2281.                     if(!draw_anim_items(sf
  2282.                     , &colors, &p, &b, save, base_name))
  2283.                         return FALSE;
  2284.                     break;
  2285.                 }
  2286.             }
  2287.         ok = TRUE;    
  2288.         free_paragraph(&p);
  2289.         }
  2290.     return ok;
  2291. }
  2292.  
  2293. //-------------------------------------------------------------------------
  2294. //    Internal routines.
  2295. //-------------------------------------------------------------------------
  2296.  
  2297. static Boolean make_sample_file(char *sample_file_name, Slide_style *sf)
  2298. /*
  2299.  * Make up a little text file that's got a sample of our stuff.
  2300.  */
  2301. {
  2302. FILE *f;
  2303. char name_only[PATH_SIZE];
  2304.  
  2305. if ((f = must_open(sample_file_name, "w")) == NULL)
  2306.     return FALSE;
  2307. fprintf(f, "-nopause\n");
  2308. fprintf(f,"Example Slide\n");
  2309. file_name_only(sf->title_font.name, name_only);
  2310. fprintf(f,"Title Font is %s\n", name_only);
  2311. file_name_only(sf->item_font.name, name_only);
  2312. fprintf(f,"Item Font is %s\n", name_only);
  2313. switch(sf->animode)
  2314.     {
  2315.     case AM_STILL:
  2316.         fprintf(f,"Output will be still images \n");
  2317.         break;
  2318.     case AM_SCROLL:
  2319.         fprintf(f, "Items will scroll across %i frames, at %i jiffies \n"
  2320.         , sf->aniframes, sf->anispeed);
  2321.         break;
  2322.     case AM_FADE:
  2323.         fprintf(f, "Items will fade through %i frames, at %i jiffies \n"
  2324.         , sf->aniframes, sf->anispeed);
  2325.         break;
  2326.     default:
  2327.         fprintf(f,"Output will be still images \n");
  2328.         break;
  2329.     }  
  2330.     
  2331. fprintf(f,  "Output Anti-aliasing is %s \n", off_on[sf->antialias]);
  2332. fclose(f);
  2333. return TRUE;
  2334. }
  2335.  
  2336. static Boolean display_sample(Slide_style *sf)
  2337. /*
  2338.  * Display current slide style sample on screen.
  2339.  */
  2340. {
  2341.     Line_file file;
  2342.     char *temp_name = "=:show'em.tmp";
  2343.     char buf[256];
  2344.  
  2345.     if (make_sample_file(temp_name, sf))
  2346.         {
  2347.         if (line_file_open(&file, temp_name, buf, sizeof(buf)))
  2348.             {
  2349.             draw_one_slide(sf, &file, AM_STILL, FALSE, NULL);
  2350.             line_file_close(&file);
  2351.             }
  2352.         DosDelete(temp_name);
  2353.         }
  2354. }
  2355.  
  2356.  
  2357. static void init_style(Slide_style *sf)
  2358. /*
  2359.  * Read in style.  If there's no style file or some other problem
  2360.  * then use default style.
  2361.  */
  2362. {
  2363.     set_default_style(sf);
  2364.     if (DosExists(persistant_style))
  2365.         read_slide_style(sf, persistant_style);
  2366. }
  2367.  
  2368. static Boolean list_slide_files(char *slide_start_name
  2369. , enum AnimMode animode, Paragraph *slide_text, Paragraph *out)
  2370. {
  2371. char flic_name[PATH_SIZE];
  2372. int i;
  2373.  
  2374. for (i=0; i<slide_text->line_count; ++i)
  2375.     {
  2376.     slide_flic_name(flic_name,  slide_start_name, i);
  2377.     if (!paragraph_add_line(out, flic_name))
  2378.         return FALSE;
  2379.     if (animode == AM_STILL)
  2380.         return TRUE;
  2381.     }
  2382. return TRUE;
  2383. }
  2384.  
  2385. static Boolean list_showem_files(Slide_style *sf, Line_file *in
  2386. , char *bat_name, Paragraph *out)
  2387. /*
  2388.  * This puts a list of all files that will be created from "bat_name"
  2389.  * in the out paragraph.
  2390.  */
  2391. {
  2392. char base_name[PATH_SIZE];
  2393. char script_name[PATH_SIZE];
  2394. char slide_start[PATH_SIZE];
  2395. int script_num = 0;
  2396. int slide_ix;
  2397. Paragraph p;
  2398. Boolean ok;
  2399.  
  2400. if (!paragraph_add_line(out, bat_name))
  2401.     return FALSE;
  2402. batch_to_base_name(bat_name, base_name);
  2403. base_to_script_name(base_name, script_name, script_num);
  2404. if (!paragraph_add_line(out, script_name))
  2405.     return FALSE;
  2406. for (slide_ix = 0; ; ++slide_ix)
  2407.     {
  2408.     strcpy(in->bat_call, "none");
  2409.     base_name_to_slide_start(base_name, slide_start, slide_ix);
  2410.     if (!init_and_read_paragraph(&p, in))
  2411.         return TRUE;
  2412.     ok = TRUE;
  2413.     if (strcmp(in->bat_call, "none") != 0)
  2414.         {
  2415.         script_num = script_num +1;
  2416.         base_to_script_name(base_name, script_name, script_num);
  2417.         ok = paragraph_add_line(out, script_name);
  2418.         }
  2419.     if (ok)
  2420.         {
  2421.         ok = list_slide_files(slide_start, sf->animode, &p, out);
  2422.         free_paragraph(&p);
  2423.         }
  2424.     if (!ok)
  2425.         return FALSE;
  2426.     }
  2427. }
  2428.  
  2429.  
  2430. static Boolean overwrite_list_ok(Paragraph *p)
  2431. /*
  2432.  * Bring up a scroller containing the paragraph and ask if it's ok to
  2433.  * overwrite it.
  2434.  */
  2435. {
  2436. int pos = 0;
  2437. int choice = 0;
  2438. int i;
  2439. char    *listbuttons[]    = {"Yes", NULL, "No"};
  2440.  
  2441. return (Qscroll(&choice, p->lines, p->line_count, &pos, listbuttons
  2442. , "Overwrite the following files?") == 1);
  2443. }
  2444.  
  2445. static Boolean make_overwrite_list(Paragraph *all, Paragraph *overwrites)
  2446. {
  2447. int i;
  2448. char *file_name;
  2449.  
  2450. for (i=0; i<all->line_count; ++i)
  2451.     {
  2452.     file_name = all->lines[i];
  2453.     if (DosExists(file_name))
  2454.         {
  2455.         if (!paragraph_add_line(overwrites, file_name))
  2456.             return FALSE;
  2457.         }
  2458.     }
  2459. return TRUE;
  2460. }
  2461.  
  2462. static Boolean overwrite_files_ok(Slide_style *sf, char *batch_name)
  2463. {
  2464. Line_file lfile;
  2465. char buf[256];
  2466. Boolean ok = FALSE;
  2467. Paragraph file_list;
  2468. Paragraph overwrite_list;
  2469.  
  2470. if (line_file_open(&lfile, persistant_text, buf, sizeof(buf)))
  2471.     {
  2472.     if (init_paragraph(&file_list))
  2473.         {
  2474.         if (list_showem_files(sf, &lfile, batch_name, &file_list))
  2475.             {
  2476.             if (init_paragraph(&overwrite_list))
  2477.                 {
  2478.                 if (make_overwrite_list(&file_list, &overwrite_list))
  2479.                     {
  2480.                     if (overwrite_list.line_count == 0)
  2481.                         ok = TRUE;
  2482.                     else
  2483.                         ok = overwrite_list_ok(&overwrite_list);
  2484.                     }
  2485.                 free_paragraph(&overwrite_list);
  2486.                 }
  2487.             }
  2488.         free_paragraph(&file_list);
  2489.         }
  2490.     line_file_close(&lfile);
  2491.     }
  2492. return ok;
  2493. }
  2494.  
  2495. static Boolean render_slides(Slide_style *sf, char *batch_name)
  2496. /*
  2497.  * Open up text file and go make as many slides as there are
  2498.  * paragraphs.  Write out commands to script too.
  2499.  */
  2500. {
  2501. Boolean ok = TRUE;
  2502. int i;
  2503. Line_file lfile;
  2504. char buf[256];
  2505. FILE *batch;
  2506. int script_num = 0;
  2507. char script_name[PATH_SIZE];
  2508. char slide_name[PATH_SIZE];
  2509. char base_name[PATH_SIZE];
  2510. static char temp_dir[PATH_SIZE];
  2511. static char ani_dir[PATH_SIZE];
  2512. Boolean script_empty;
  2513. ok = FALSE;
  2514.     
  2515. /* Figure out base name of numbered flics.  Will convert something
  2516.  * like C:\ANI\1STQUARTR.SCR into C:\ANI\1STQ  */
  2517.  
  2518. batch_to_base_name(batch_name, base_name);
  2519. GetDir(ani_dir);
  2520. GetResourceDir(temp_dir);
  2521. SetDir(temp_dir);
  2522. SetDir("..");
  2523. strcpy(temp_dir, ani_dir);
  2524. GetDir(ani_dir);
  2525. SetDir(temp_dir);
  2526.  
  2527. if (line_file_open(&lfile, persistant_text, buf, sizeof(buf)))
  2528.     {
  2529.     if ((batch = must_open(batch_name, "w")) != NULL)
  2530.         {
  2531.         fprintf(batch, "@echo off \n");
  2532.         base_to_script_name(base_name, script_name, script_num);
  2533.         if ((script = must_open(script_name, "w")) != NULL)
  2534.             {
  2535.             for (i=0; ; ++i)  /* Keep count. */
  2536.                 {
  2537.                 strcpy(lfile.x_call, "none");
  2538.                 strcpy(lfile.bat_call, "none");
  2539.                 base_name_to_slide_start(base_name, slide_name, i);
  2540.                 if(draw_one_slide(sf
  2541.                 , &lfile, sf->animode, TRUE, slide_name))
  2542.                     {
  2543.                     if (strcmp(lfile.x_call, "none") != 0)
  2544.                         {
  2545.                         fprintf(script, "%s \n", lfile.x_call);
  2546.                         strcpy(lfile.x_call, "none");
  2547.                         }
  2548.                     if (strcmp(lfile.bat_call, "none") != 0)
  2549.                         {
  2550.                         if (ftell(script) != 0)
  2551.                             {
  2552.                             fprintf(script,"Exittodos \n");
  2553.                             fprintf(batch
  2554.                             , "%sANIPLAY -AUTO -CFG %sAA.CFG %s \n"
  2555.                             , ani_dir, ani_dir, script_name);
  2556.                             }
  2557.                         fprintf(batch,"%s \n",lfile.bat_call);
  2558.                         fclose(script);
  2559.                         script_num = script_num +1;
  2560.                         base_to_script_name(base_name, script_name
  2561.                         , script_num);
  2562.                         if((script = must_open(script_name,"w")) == NULL)
  2563.                             {
  2564.                             ok = FALSE;
  2565.                             break;
  2566.                             }
  2567.                         strcpy(lfile.bat_call, "none");
  2568.                         }
  2569.                     }
  2570.                 else
  2571.                     {
  2572.                     ok = TRUE;
  2573.                     break;
  2574.                     }
  2575.                 }
  2576.             script_empty = (ftell(script) == 0);
  2577.             fclose(script);
  2578.             if(!script_empty)
  2579.                 {
  2580.                 fprintf(batch,"%sANIPLAY -AUTO -CFG %sAA.CFG %s \n",
  2581.                           ani_dir, ani_dir, script_name);
  2582.                 }
  2583.             else
  2584.                 {
  2585.                 DosDelete(script_name);
  2586.                 }
  2587.             }
  2588.         fclose(batch);
  2589.         }
  2590.     line_file_close(&lfile);
  2591.     }
  2592. return ok;
  2593. }
  2594.  
  2595. static Boolean preview_slides(Slide_style *sf)
  2596. /*
  2597.  * Put up one slide after the other,  pausing for a key press or
  2598.  * mouse click between each one.
  2599.  */
  2600. {
  2601.     Line_file lfile;
  2602.     char buf[256];
  2603.     Boolean ok = FALSE;
  2604.     Boolean go_on;
  2605.     int i;
  2606.     int x,y,l,r,key;
  2607.  
  2608.     HideCursor();
  2609.     if (line_file_open(&lfile, persistant_text, buf, sizeof(buf)))
  2610.         {
  2611.         printf("Press any key or click to continue, escape to abort.");
  2612.         for (i=0; ; ++i)  /* Keep count. */
  2613.             {
  2614.             strcpy(lfile.x_call, "none");
  2615.             strcpy(lfile.bat_call, "none");
  2616.             if (!draw_one_slide(sf, &lfile, sf->animode, FALSE, NULL))
  2617.                 break;
  2618.             else
  2619.                 ok = TRUE;
  2620.             if (strcmp(lfile.x_call, "none") != 0)
  2621.                 Qtext("\"%s\"\n\nwill be written to the script."
  2622.                 , lfile.x_call);
  2623.             else if (strcmp(lfile.bat_call, "none") != 0)
  2624.                 Qtext("\"%s\"\n\nwill be written to the batch file."
  2625.                 , lfile.bat_call);
  2626.             else 
  2627.                 {
  2628.                 if (wait_for_escape())
  2629.                     {
  2630.                     unprintf();
  2631.                     break;
  2632.                     }
  2633.                 }
  2634.             unprintf();
  2635.             }
  2636.         line_file_close(&lfile);
  2637.         }
  2638.     ShowCursor();
  2639.     return ok;
  2640. }
  2641.  
  2642. Boolean save_text(char *file_name)
  2643. /*
  2644.  * Copy temp text file to a real file.
  2645.  */
  2646. {
  2647. text_changed = FALSE;
  2648. return copy_file(persistant_text, file_name);
  2649. }
  2650.  
  2651. Boolean qsave_text()
  2652. /* 
  2653.  * Bring up file requestor to save text file.
  2654.  */
  2655. {
  2656. Boolean ok = FALSE;
  2657. char name_buf[PATH_SIZE];
  2658.  
  2659. strcpy(name_buf, text_file_name);
  2660. if (Qfile(".TXT", "Save"
  2661. , name_buf, name_buf, TRUE,  "Save Slide Text File"))
  2662.     {
  2663.     /* If it's the same as it was last loaded/saved just
  2664.      * save it. */
  2665.     if (text_named && (stricmp(text_file_name, name_buf) == 0))
  2666.         {
  2667.         save_text(name_buf);
  2668.         ok = TRUE;
  2669.         }
  2670.     /* If it's a new name make sure they aren't overwriting
  2671.      * something. */
  2672.     else if (overwrite_ok(name_buf))
  2673.         {
  2674.         save_text(name_buf);
  2675.         ok = TRUE;
  2676.         }
  2677.     text_named = TRUE;
  2678.     strcpy(text_file_name, name_buf);
  2679.     }
  2680. return ok;
  2681. }
  2682.  
  2683. Boolean insure_text(char *prompt_string)
  2684. /*
  2685.  * Check to see if text has changed.  If it has prompt user to save it.
  2686.  * Note that prompt string should contain a %s where you want text_file_name
  2687.  * to appear.
  2688.  */
  2689. {
  2690. char *buttons[] = {"Yes", "No", "Cancel",};
  2691. int choice;
  2692.  
  2693. if (!text_changed)
  2694.     return TRUE;
  2695. choice = Qchoice(buttons, Array_els(buttons), prompt_string, text_file_name);
  2696. switch (choice)
  2697.     {
  2698.     case 1: /* Yes */
  2699.         if (text_named)
  2700.             return save_text(text_file_name);
  2701.         else         /* Check for overwrite if it's "unnamed.txt" */
  2702.             {
  2703.             if (!overwrite_ok(text_file_name))
  2704.                 return FALSE;
  2705.             save_text(text_file_name);
  2706.             }
  2707.     case 2: /* No */
  2708.         return TRUE;
  2709.     default: /* Cancel */
  2710.         return FALSE;
  2711.     }
  2712. }
  2713.  
  2714. //-------------------------------------------------------------------------
  2715. // Routines that interact with User
  2716. //-------------------------------------------------------------------------
  2717. Boolean css_menu(Slide_style *sf)
  2718. /*
  2719.  * Interpret the create slide show menu.
  2720.  */
  2721. {
  2722. int choice;
  2723. static int cursor_pos, line_pos;
  2724. static char bat_name[PATH_SIZE] = "show'em.scr";
  2725. short css_flags[Array_els(css_choices)];
  2726.  
  2727. for (;;)
  2728.     {
  2729.     memset(css_flags, 0, sizeof(css_flags));
  2730.     if (!DosExists(persistant_text))
  2731.         {
  2732.         css_flags[CSS_RENDER] = css_flags[CSS_NEW]
  2733.         = css_flags[CSS_PREVIEW] = css_flags[CSS_SAVE] = QMF_DISABLED;
  2734.         }
  2735.     choice = QmenuWithFlags(css_choices, Array_els(css_choices)
  2736.     , css_flags, css_header);
  2737.     switch(choice)
  2738.         {
  2739.         case CSS_HELP:
  2740.             multi_screen_help(css_help, Array_els(css_help));
  2741.             break;
  2742.         case CSS_EDIT:
  2743.             QeditFile(persistant_text, &cursor_pos, &line_pos);
  2744.             text_changed = TRUE;
  2745.             break;
  2746.         case CSS_LOAD:
  2747.             if (insure_text("Save %s before loading?"))
  2748.                 {
  2749.                 if (Qfile(".TXT", "Load", text_file_name, text_file_name
  2750.                 , FALSE, "Load Slide Text File"))
  2751.                     {
  2752.                     copy_file(text_file_name, persistant_text);
  2753.                     text_changed = FALSE;
  2754.                     text_named = TRUE;
  2755.                     }
  2756.                 }
  2757.             break;
  2758.         case CSS_SAVE:
  2759.             qsave_text();
  2760.             break;
  2761.         case CSS_NEW:
  2762.             {
  2763.             if (insure_text("Save %s before starting new text?"))
  2764.                 {
  2765.                 DosDelete(persistant_text);
  2766.                 text_named = text_changed = FALSE;
  2767.                 strcpy(text_file_name,  UNTITLED_TEXT);
  2768.                 }
  2769.             }
  2770.             break;
  2771.         case CSS_PREVIEW:
  2772.             preview_slides(sf);
  2773.             break;
  2774.         case CSS_RENDER:
  2775.             if (Qfile(".BAT", "Save", bat_name, bat_name
  2776.             , TRUE, "Render slides?"))
  2777.                 {
  2778.                 if (overwrite_files_ok(sf, bat_name))
  2779.                     {
  2780.                     if (render_slides(sf, bat_name))
  2781.                         return FALSE;  /* Get out of program! */
  2782.                     }
  2783.                 }
  2784.             break;
  2785.         default:
  2786.             return TRUE;
  2787.         }
  2788.     }
  2789. }
  2790.  
  2791.  
  2792. Boolean load_new_font(Font_style *fs)
  2793. /*
  2794.  * Load font and record the name and size.
  2795.  */
  2796. {
  2797.     Font_style new_style;
  2798.     char full_font_name[PATH_SIZE];
  2799.  
  2800.     /* Load up the current selection */
  2801.     set_font_style(fs);
  2802.     /* Go to font requestor. */
  2803.     Qfont();
  2804.     get_font_style(&new_style);
  2805.     /* Return whether it's a new one */
  2806.     if (memcmp(fs, &new_style, sizeof(new_style)) != 0)
  2807.         {
  2808.         memcpy(fs, &new_style, sizeof(*fs));
  2809.         return TRUE;
  2810.         }
  2811.     else
  2812.         return FALSE;
  2813. }
  2814.  
  2815. void title_menu(Slide_style *sf)
  2816. /*
  2817.  * Interpret title menu
  2818.  */
  2819. {
  2820.     int choice;
  2821.     int just_choice;
  2822.     Boolean is_changed;
  2823.     int color;
  2824.     int x,y,w,h;
  2825.  
  2826.     for (;;)
  2827.         {
  2828.         is_changed = FALSE;
  2829.         choice = Qmenu(title_choices, Array_els(title_choices), title_header);
  2830.         switch(choice)
  2831.             {
  2832.             case TITLE_COLOR:
  2833.                 if ((color = Qcolor()) >= Success)
  2834.                     {
  2835.                     translate_to_rgb(color, &sf->title_color);
  2836.                     is_changed = TRUE;
  2837.                     }
  2838.                 break;
  2839.             case TITLE_POS:
  2840.                 TitleSetText("Example Slide");
  2841.                 set_font_style(&sf->title_font);
  2842.                 SetJustify(sf->title_justification);
  2843.                 TitleSetPosition(sf->title_position.x, sf->title_position.y
  2844.                 ,  get_title_width(sf),  FontHeight());
  2845.                 TitleEdit();
  2846.                 TitleGetPosition(&x,&y,&w,&h);
  2847.                 if (x != sf->title_position.x || y != sf->title_position.y)
  2848.                     {
  2849.                     sf->title_position.x = x;
  2850.                     sf->title_position.y = y;
  2851.                     is_changed = TRUE;
  2852.                     }
  2853.                 break;
  2854.             case TITLE_JUST:
  2855.                 if (just_choice = Qmenu(title_just_choices
  2856.                                 , Array_els(title_just_choices)
  2857.                                 , title_just_header));
  2858.                     if (just_choice-1 != sf->title_justification
  2859.                         && just_choice != 0)
  2860.                         {
  2861.                         sf->title_justification = just_choice-1;
  2862.                         is_changed = TRUE;
  2863.                         }
  2864.                 break;
  2865.             case TITLE_FONT:
  2866.                 is_changed = load_new_font(&sf->title_font);
  2867.                 break;
  2868.             default:
  2869.                 return;
  2870.             }
  2871.         if (is_changed)
  2872.             display_sample(sf);
  2873.         }
  2874. }
  2875.  
  2876. void item_menu(Slide_style *sf)
  2877. /*
  2878.  * Interpret item menu
  2879.  */
  2880. {
  2881.     int choice;
  2882.     Boolean is_changed;
  2883.     int color;
  2884.  
  2885.     for (;;)
  2886.         {
  2887.         choice = Qmenu(item_choices, Array_els(item_choices), item_header);
  2888.         switch(choice)
  2889.             {
  2890.             case ITEM_COLOR:
  2891.                 if ((color = Qcolor()) >= Success)
  2892.                     {
  2893.                     translate_to_rgb(color, &sf->item_color);
  2894.                     is_changed = TRUE;
  2895.                     }
  2896.                 break;
  2897.             case ITEM_FONT:
  2898.                 is_changed = load_new_font(&sf->item_font);
  2899.                 break;
  2900.             default:
  2901.                 return;
  2902.             }
  2903.         if (is_changed)
  2904.             display_sample(sf);
  2905.         }
  2906. }
  2907.  
  2908. void bullet_menu(Slide_style *sf)
  2909. /*
  2910.  * Interpret bullet menu
  2911.  */
  2912. {
  2913.     int choice;
  2914.     Boolean is_changed;
  2915.     char header[80];
  2916.     char file_name[32];
  2917.     char bullet_name[PATH_SIZE];
  2918.     int color;
  2919.     
  2920.     strcpy(bullet_name, sf->bullet_image);
  2921.  
  2922.     for (;;)
  2923.         {
  2924.         file_name_only(sf->bullet_image, file_name);
  2925.         sprintf(header, "%s (%s)", bullet_header, file_name);
  2926.         is_changed = FALSE;
  2927.         choice = Qmenu(bullet_choices, Array_els(bullet_choices), header);
  2928.         switch(choice)
  2929.             {
  2930.             case BULLET_COLOR:
  2931.                 if ((color = Qcolor()) >= Success)
  2932.                     {
  2933.                     translate_to_rgb(color, &sf->bullet_color);
  2934.                     strcpy(sf->bullet_image, "circle");
  2935.                     is_changed = TRUE;
  2936.                     }
  2937.                 break;
  2938.             case BULLET_CIRCLE:
  2939.                 if (!stricmp(sf->bullet_image, "circle") == 0)
  2940.                     {
  2941.                     strcpy(sf->bullet_image, "circle");
  2942.                     is_changed = TRUE;
  2943.                     }
  2944.                 break;
  2945.             case BULLET_USE_CEL:
  2946.                 if (Qfile(".CEL;.FL?", "Load"
  2947.                 , bullet_name, bullet_name
  2948.                 , FALSE, "Load Bullet Image"))
  2949.                     if (LoadCel(bullet_name) >= Success)
  2950.                         {
  2951.                         strcpy(sf->bullet_image, bullet_name);
  2952.                         is_changed = TRUE;
  2953.                         }
  2954.                 break;
  2955.             case BULLET_NONE:
  2956.                 if (!stricmp(sf->bullet_image, "none") == 0)
  2957.                     {
  2958.                     strcpy(sf->bullet_image, "none");
  2959.                     is_changed = TRUE;
  2960.                     }
  2961.                 break;
  2962.             default:
  2963.                 return;
  2964.             }
  2965.         if (is_changed)
  2966.             display_sample(sf);
  2967.     }
  2968. }  
  2969.  
  2970. void background_menu(Slide_style *sf)
  2971. /* 
  2972.  * Interpret background menu.
  2973.  */
  2974. {
  2975.     int choice;
  2976.     char file_name[32];
  2977.     char header[80];
  2978.     int color;
  2979.     char background_name[PATH_SIZE];
  2980.     Boolean is_changed;
  2981.  
  2982.     strcpy(background_name, sf->background_image);
  2983.  
  2984.     for (;;)
  2985.         {
  2986.         file_name_only(sf->background_image, file_name);
  2987.         sprintf(header, "%s (%s)", background_header, file_name);
  2988.         is_changed = FALSE;
  2989.         choice = Qmenu(background_choices
  2990.         , Array_els(background_choices), header);
  2991.         switch(choice)
  2992.             {
  2993.             case BACKGROUND_GET_COLOR:
  2994.                 if ((color = Qcolor()) >= Success)
  2995.                     {
  2996.                     translate_to_rgb(color, &sf->background_color);
  2997.                 if (is_solid(sf->background_image)
  2998.                 ||  is_gradient(sf->background_image))
  2999.                      is_changed = TRUE;
  3000.                     }
  3001.                 break;
  3002.             case BACKGROUND_SOLID:
  3003.             if (!is_solid(sf->background_image))
  3004.                     {
  3005.                     strcpy(sf->background_image, "solid");
  3006.                     is_changed = TRUE;
  3007.                     }
  3008.                 break;
  3009.             case BACKGROUND_GRADIENT:
  3010.             if (!is_gradient(sf->background_image))
  3011.                     {
  3012.                     strcpy(sf->background_image, "gradient");
  3013.                     is_changed = TRUE;
  3014.                     }
  3015.                 break;
  3016.             case BACKGROUND_USE_PIC:
  3017.                 if (Qfile(".GIF;.FL?;.PCX", "Load"
  3018.                 , background_name, background_name
  3019.                 , FALSE, "Load Background Image"))
  3020.                     {
  3021.                     if (LoadPic(background_name) >= Success)
  3022.                         {
  3023.                         strcpy(sf->background_image, background_name);
  3024.                         SwapClip();
  3025.                         display_sample(sf);
  3026.                         }
  3027.                     }
  3028.                 break;
  3029.             default:
  3030.                 return;
  3031.             }
  3032.         if (is_changed)
  3033.             {
  3034.             preload_background(sf);
  3035.             display_sample(sf);
  3036.             }
  3037.         }
  3038. }
  3039.  
  3040. void logo_menu(Slide_style *sf)
  3041. /*
  3042.  * Interpret logo menu
  3043.  */
  3044. {
  3045.     int choice;
  3046.     Boolean is_changed;
  3047.     char header[80];
  3048.     char file_name[32];
  3049.     char logo_name[PATH_SIZE];
  3050.     int choice_count;
  3051.  
  3052.     strcpy(logo_name, sf->logo_image);
  3053.     
  3054.     for (;;)
  3055.         {
  3056.         file_name_only(sf->logo_image, file_name);
  3057.         sprintf(header, "%s (%s)", logo_header, file_name);
  3058.         is_changed = FALSE;
  3059.         choice = Qmenu(logo_choices, Array_els(logo_choices), header);
  3060.         switch(choice)
  3061.             {
  3062.             case LOGO_USE_CEL:
  3063.                 if (Qfile(".CEL;.FL?", "Load"
  3064.                 , logo_name, logo_name
  3065.                 , FALSE, "Load Logo Image"))
  3066.                     {
  3067.                     if (LoadCel(logo_name) >= Success)
  3068.                         {
  3069.                         strcpy(sf->logo_image, logo_name);
  3070.                         is_changed = TRUE;
  3071.                         }
  3072.                     }
  3073.                 break;
  3074.             case LOGO_POSITION:
  3075.                 {
  3076.                 if (stricmp(sf->logo_image, "none") != 0)
  3077.                     {
  3078.                     if (LoadCel(sf->logo_image) >= Success)
  3079.                         {
  3080.                         int x,y,w,h;
  3081.  
  3082.                         GetScreenSize(GetCelScreen(), &w, &h);
  3083.                         x = sf->logo_position.x - w/2;
  3084.                         y = sf->logo_position.y - h/2;
  3085.                         if (DragBox(&x,&y,&w,&h))
  3086.                             {
  3087.                             sf->logo_position.x = x + w/2;
  3088.                             sf->logo_position.y = y + h/2;
  3089.                             is_changed = TRUE;
  3090.                             }
  3091.                         }
  3092.                     }
  3093.                 }
  3094.                 break;
  3095.             case LOGO_NONE:
  3096.                 if (!stricmp(sf->logo_image, "none") == 0)
  3097.                     {
  3098.                     strcpy(sf->logo_image, "none");
  3099.                     is_changed = TRUE;
  3100.                     }
  3101.                 break;
  3102.             default:
  3103.                 return;
  3104.             }
  3105.         if (is_changed)
  3106.             display_sample(sf);
  3107.         }
  3108. }
  3109.  
  3110. static Boolean ani_settings(Slide_style *sf)
  3111. {
  3112.     Boolean ok = FALSE;
  3113.     int i;
  3114.     int x;
  3115.     char prompt[80];
  3116.  
  3117.     sprintf(prompt,"Select number of frames per item, currently %i"
  3118.     ,  sf->aniframes);
  3119.     i = sf->aniframes;
  3120.     if (!Qnumber(&i, 1, 100, prompt))
  3121.         return FALSE;
  3122.     if(i < 100 || i > 0)
  3123.         {
  3124.         sprintf(prompt, "Select playback speed, currently %i"
  3125.         , sf->anispeed);
  3126.         x = sf->anispeed;
  3127.         Qnumber(&x, 0, 100, prompt);
  3128.         if(x > 0 || x < 100)
  3129.             {
  3130.             sf->aniframes = i;
  3131.             sf->anispeed = x;
  3132.             ok = TRUE;
  3133.             }
  3134.         else
  3135.             Qtext("Speed must be between 1, and 100");
  3136.         }
  3137.     else
  3138.         Qtext("Frames per item must be between 1, and 100");
  3139.  
  3140. return ok;
  3141. }
  3142.  
  3143. void out_menu(Slide_style *sf)
  3144. /* 
  3145.  * Interpret output menu.
  3146.  */
  3147. {
  3148.     int choice;
  3149.     char anti_line[40];
  3150.     char safe_line[40];
  3151.     Boolean is_changed = FALSE;
  3152.     short out_flags[Array_els(out_choices)];
  3153.     int i;
  3154.  
  3155.     for (;;)
  3156.         {
  3157.         /* First set up the asterisks in the menu. */
  3158.         memset(out_flags, 0, sizeof(out_flags));    /* Clear flags */
  3159.         if (sf->antialias)         
  3160.             out_flags[OUT_ANTIALIAS] = QMF_ASTERISK;
  3161.         if (sf->safe_title)        
  3162.             out_flags[OUT_SAFE_TITLE] = QMF_ASTERISK;
  3163.         switch (sf->animode)
  3164.             {
  3165.             case AM_STILL:
  3166.                 out_flags[OUT_STILL] = QMF_ASTERISK;
  3167.                 break;
  3168.             case AM_SCROLL:
  3169.                 out_flags[OUT_SCROLL] = QMF_ASTERISK;
  3170.                 break;
  3171.             case AM_FADE:
  3172.                 out_flags[OUT_FADE] = QMF_ASTERISK;
  3173.                 break;
  3174.             }
  3175.         choice = QmenuWithFlags(out_choices, Array_els(out_choices)
  3176.         , out_flags, out_header);
  3177.         switch(choice)
  3178.             {
  3179.             case OUT_HELP:
  3180.                 Qtext(out_help1);
  3181.                 break;
  3182.             case OUT_STILL:
  3183.                 if(!sf->animode == AM_STILL)
  3184.                     {
  3185.                     sf->animode = AM_STILL;
  3186.                     display_sample(sf);
  3187.                     }
  3188.                 break;
  3189.             case OUT_SCROLL:
  3190.                 if(!sf->animode == AM_SCROLL || (ani_settings(sf)))
  3191.                     {
  3192.                     sf->animode = AM_SCROLL;
  3193.                     display_sample(sf);
  3194.                     }
  3195.                 break;
  3196.             case OUT_FADE:
  3197.                 if(!sf->animode == AM_FADE || (ani_settings(sf)))
  3198.                     {
  3199.                     sf->animode = AM_FADE;
  3200.                     display_sample(sf);
  3201.                     }
  3202.                 break;
  3203.             case OUT_ANTIALIAS:
  3204.                 sf->antialias = !sf->antialias;
  3205.                 display_sample(sf);
  3206.                 break;
  3207.             case OUT_SAFE_TITLE:
  3208.                 sf->safe_title = !sf->safe_title;
  3209.                 preload_background(sf);
  3210.                 display_sample(sf);
  3211.                 break;
  3212.             case OUT_PREVIEW:
  3213.                 preview_slides(sf);
  3214.                 break;
  3215.             default:
  3216.                 return;
  3217.             }
  3218.         }
  3219.     return;
  3220. }
  3221.  
  3222. void ssf_menu(Slide_style *sf)
  3223. /*
  3224.  * Set Slide Style menu.
  3225.  */
  3226. {
  3227. int choice;
  3228. static char file_name[PATH_SIZE] = "show'em.sss";
  3229. char anti_line[40];
  3230.  
  3231. for (;;)
  3232.     {
  3233.     choice = Qmenu(ssf_choices, Array_els(ssf_choices), ssf_header);
  3234.     switch(choice)
  3235.         {
  3236.         case SSF_HELP:
  3237.             Qtext(ssf_help);
  3238.             break;
  3239.         case SSF_TITLE:
  3240.             title_menu(sf);
  3241.             break;
  3242.         case SSF_ITEMS:
  3243.             item_menu(sf);
  3244.             break;
  3245.         case SSF_BULLET:
  3246.             bullet_menu(sf);
  3247.             break;
  3248.         case SSF_BACKGROUND:
  3249.             background_menu(sf);
  3250.             break;
  3251.         case SSF_LOGO:
  3252.             logo_menu(sf);
  3253.             break;
  3254.         case SSF_OUTPUT:
  3255.             out_menu(sf);
  3256.             break;
  3257.         case SSF_LOAD:
  3258.             if (Qfile(".SSS", "Load",  file_name, file_name
  3259.             , TRUE,  "Load Show'em Slide Style"))
  3260.                 {
  3261.                 read_slide_style(sf, file_name);
  3262.                 preload_background(sf);
  3263.                 display_sample(sf);
  3264.                 }
  3265.             break;
  3266.         case SSF_SAVE:
  3267.             if (Qfile(".SSS", "Save",  file_name, file_name
  3268.             , TRUE,  "Save Show'em Slide Style"))
  3269.                 if (overwrite_ok(file_name))
  3270.                     if (!write_slide_style(sf, file_name))
  3271.                         Qtext("Could not save Style %s", file_name);
  3272.             break;
  3273.         default:
  3274.             return;
  3275.         }
  3276.     }
  3277. }
  3278.  
  3279.  
  3280.  
  3281. void mm_menu(Slide_style *sf)
  3282. /*
  3283.  * Interpret the top level menu.
  3284.  */
  3285. {
  3286. int choice;
  3287.  
  3288. for (;;)
  3289.     {
  3290.     choice = Qmenu(mm_choices, Array_els(mm_choices), mm_header);
  3291.     switch(choice)
  3292.         {
  3293.         case MAIN_HELP:
  3294.             multi_screen_help(mm_help, Array_els(mm_help));
  3295.             break;
  3296.         case MAIN_CREATE:
  3297.             if (!css_menu(sf))
  3298.                 return;
  3299.             break;
  3300.         case MAIN_FORMAT:
  3301.             ssf_menu(sf);
  3302.             break;
  3303.         default:
  3304.             return;
  3305.         }
  3306.     }
  3307. }
  3308.     
  3309.  
  3310. main()
  3311. {
  3312.     Slide_style style;
  3313.  
  3314.     if (ignore_changes())
  3315.         {
  3316.         SetAbort(FALSE);
  3317.         load_persistant();
  3318.         GetSize(&slide_width, &slide_height);
  3319.         shadow_xoff = slide_width/200;
  3320.         shadow_yoff = slide_height/150;
  3321.         SetFrameCount(1);
  3322.         init_style(&style);
  3323.         if (preload_background(&style))
  3324.             {
  3325.             display_sample(&style);
  3326.             mm_menu(&style);
  3327.             write_slide_style(&style, persistant_style);
  3328.             save_persistant();
  3329.             }
  3330.         SwapRelease();
  3331.         }
  3332. }
  3333.  
  3334.